Example #1
0
static void _message(S_SCR_INFO *psSI,BOOL bClear,CHAR *lpMessage)
{
	HDC hdc;
	RECT rWin;
	SIZE sWin;
	HFONT hFont,hFontOld=NULL;
	RECT rText;
	SIZE sText;

	hdc=GetDC(psSI->ObjClient->hWnd);
	GetWindowRect(psSI->ObjClient->hWnd,&rWin);
	sWin.cx=rWin.right-rWin.left+1;
	sWin.cy=rWin.bottom-rWin.top+1;
	
	sText.cx=180; sText.cy=50; // Larghezza ed altezza del rettangolo
	
	rText.left=(sWin.cx-sText.cx)/2; rText.right=rText.left+sText.cx+1;
	rText.top=(sWin.cy-sText.cy)/2; rText.bottom=rText.top+sText.cy+1;

	if (bClear) {

		RECT rArea;
		_(rArea);
		rArea.right=sWin.cx-1; rArea.bottom=sWin.cy-1;
		dcBoxBrush(hdc,&rArea,HS_BDIAGONAL,sys.Color3DShadow,sys.Color3DLight);
		/*
		RECT rArea;
//		HBRUSH backBrush=CreateSolidBrush(sys.Color3DShadow);
		HBRUSH diagBrush=CreateHatchBrush(HS_BDIAGONAL,sys.Color3DLight);
		SetBkColor(hdc,sys.Color3DShadow);
		_(rArea);
		rArea.right=sWin.cx-1; rArea.bottom=sWin.cy-1;
//		FillRect(hdc, &rArea, backBrush);
		FillRect(hdc, &rArea, diagBrush);
//		DeleteObject(backBrush);
		DeleteObject(diagBrush);
		*/
	}

	if (!strEmpty(lpMessage)) {

		RECT rcText;
		SIZE sCalc;
		SetBkMode(hdc,OPAQUE);
		SetBkColor(hdc,RGB(255,255,255));
		SetTextColor(hdc,RGB(120,120,120));

		hFont=GetStockObject(SYSTEM_FONT);
		hFontOld = SelectObject(hdc, hFont);
		dcRectRound(hdc,&rText,ColorLum(sys.Color3DShadow,-20),RGB(255,255,255),24,24,3);

		_(rcText);
		DrawText(hdc,
				 lpMessage,strlen(lpMessage),
				 &rcText,    // pointer to struct with formatting dimensions
				 DT_CALCRECT// text-drawing flags
				);

		sizeCalc(&sCalc,&rcText);
		
		//rText.left
		rText.left+=2; 
		rText.top+=(sText.cy-sCalc.cy)>>1;
		//rText.right
		//rText.right-=2; rText.bottom-=2;

		DrawText(hdc,
				 lpMessage,
				 strlen(lpMessage),
				 &rText,    // pointer to struct with formatting dimensions
				 DT_CENTER|DT_VCENTER// text-drawing flags
				);
	}
Example #2
0
//
// imgResize(()
//
BOOL imgResize(IMG_RESIZE * psImgResize)
{
	CHAR *lpMess="";
	INT fTrack=FALSE;
	INT iErr;
	EN_FILE_TYPE enImageType=0;
    IMGHEADER ImgHead;
	POINT ptArea;
	POINT ptPhoto;
	RECT srRectSource,srRectLogo;

	SIZE sDest; // Dimensione destinazione
	RECT rDest; // Rettangolo destinazione

	INT		hdlImage;
	INT		hdlImageNew;
	INT		hdlImageEnd;
	SIZE	sPhotoDest;
	DWORD	dw;
	BOOL	bFillBack;

	if (!psImgResize->pszFileSource) return TRUE;

	// 
	// Controllo se esiste il file
	//
	if (!fileCheck(psImgResize->pszFileSource)) 
	{
		printf("Il file %s non esiste",psImgResize->pszFileSource);
		ehLogWrite("Il file %s non esiste",psImgResize->pszFileSource);
		return TRUE;
	}

	// 
	// Controllo LogoFile
	//
	if (*psImgResize->sLogo.szFile)
	{
		if (!fileCheck(psImgResize->sLogo.szFile)) 
		{
			printf("Il logofile %s non esiste",psImgResize->sLogo.szFile);
			ehLogWrite("Il logofile %s non esiste",psImgResize->sLogo.szFile);
			return TRUE;
		}
	}

//	remove(szNewFile);

	// ------------------------------------------------------------------------
	// A) Leggere le dimensioni del sorgente
	//
	
	enImageType=IMG_UNKNOW;
	switch (isImage(psImgResize->pszFileSource))
	{
		case IMG_JPEG:
			if (JPGReadHeader(psImgResize->pszFileSource,&ImgHead,JME_HIDE)) enImageType=IMG_JPEG;
			break;

		case IMG_GIF:
			if (GIFReadHeader(psImgResize->pszFileSource,&ImgHead,JME_HIDE)) enImageType=IMG_GIF;
			break;

		case IMG_PNG:
			if (PNGReadHeader(psImgResize->pszFileSource,&ImgHead,JME_HIDE)) enImageType=IMG_PNG;
			break;
		
		default:
			break;
	}

	if (!enImageType)
	{
//		printf("ko");
		printf("%s: errore in lettura Header",psImgResize->pszFileSource);
		ehLogWrite("%s: errore in lettura Header",psImgResize->pszFileSource);
		return TRUE;
	}
	

	sPhotoDest.cx=(INT) (psImgResize->sFix.cx*psImgResize->sPhoto.dPerc/100);
	sPhotoDest.cy=(INT) (psImgResize->sFix.cy*psImgResize->sPhoto.dPerc/100);

	// 
	// B) Calcolare le nuove dimensioni
	//
	IMGCalcSize(&ImgHead,		// Dimensioni del sorgente
				&sPhotoDest,	// Area disponibile
				psImgResize->psMin,
				psImgResize->psMax,
				psImgResize->enPhotoAdatta,  // Tipo di adattamento
				psImgResize->sPhoto.iAlignHor,	   // Allineamento orizzontale
				psImgResize->sPhoto.iAlignVer,	   // Allineamento verticale
				&sDest,		   // Dimensioni della destinazione
				&rDest,
				&srRectSource); 	   // Posizionamento in destinazione
	if (!sPhotoDest.cy||!sPhotoDest.cx) 
		memcpy(&sPhotoDest,&sDest,sizeof(sDest));

	memcpy(&psImgResize->sDest,&sDest,sizeof(sDest));
	//
	// C) Carica il sorgente in memoria
	//
	switch (ImgHead.enType)
	{
		BOOL bError=false;
		
		case IMG_JPEG:

			//
			// Lettura veloce
			//
			if (psImgResize->bQuickLoading) {

				INT iPerc,iFactor;
				SIZE sizSource,sAp1;
				RECT sAp2;
				sizSource.cx=ImgHead.bmiHeader.biWidth;
				sizSource.cy=ImgHead.bmiHeader.biHeight;
				iFactor=JPGGetFactor(&sizSource,&sPhotoDest,&iPerc);
				bError=!JPGReadFileEx(psImgResize->pszFileSource,&hdlImage,NULL,iFactor,JDCT_IFAST,NULL,FALSE,IMG_PIXEL_RGB);
				if (!bError) {
						
					// Letto + piccolo, calcolo nuove dimensioni
					IMGHEADER * psImgHead;
					//printf("[%d:%d]" CRLF,bError,hdlImage);
					if (hdlImage>-1) {
						psImgHead=(IMGHEADER *) memoLock(hdlImage);
						IMGCalcSize(psImgHead,      // Dimensioni del sorgente
									&sPhotoDest,	   // Area disponibile
									psImgResize->psMin,
									psImgResize->psMax,
									psImgResize->enPhotoAdatta,  // Tipo di adattamento
									psImgResize->sPhoto.iAlignHor,	   // Allineamento orizzontale
									psImgResize->sPhoto.iAlignVer,	   // Allineamento verticale
									&sAp1,		   // Dimensioni della destinazione
									&sAp2,
									&srRectSource); 	   // Posizionamento in destinazione				
									}
						memoUnlockEx(hdlImage,"a1");
					} else bError=TRUE;
			}
			//
			// Lettura dell'intera immagine
			//
			else {
				bError=!JPGReadFile(psImgResize->pszFileSource,&hdlImage,NULL,NULL,FALSE,IMG_PIXEL_RGB);
			}

			if (bError)
			{
#ifdef EH_CONSOLE
				printf("ko:[%s] errore in lettura JPG",psImgResize->pszFileSource);
#endif
				ehLogWrite("%s: errore in lettura JPG",psImgResize->pszFileSource);
				return TRUE;
			}
			//hdlImage=IMGToRGB(hdlImage,1);
			break;

		case IMG_GIF:
			if (!GIFReadFile(psImgResize->pszFileSource,&hdlImage,psImgResize->cBackColor,FALSE,IMG_PIXEL_RGB)) 
			{
				printf("ko");
				printf("%s: errore in lettura GIF",psImgResize->pszFileSource);
				ehLogWrite("%s: errore in lettura GIF",psImgResize->pszFileSource);
				printf("Errore"); //getch();
				return TRUE;
			}
			break;

		case IMG_PNG:
			if (!PNGReadFile(psImgResize->pszFileSource,&hdlImage,NULL,FALSE)) 
			{
				printf("ko");
				printf("%s: errore in lettura PNG",psImgResize->pszFileSource);
				ehLogWrite("%s: errore in lettura PNG",psImgResize->pszFileSource);
				printf("Errore"); //getch();
				return TRUE;
			}
			break;

		default:
			printf("ko");
			printf("%s: formato non gestito",psImgResize->pszFileSource);
			ehLogWrite("%s: formato non gestito",psImgResize->pszFileSource);
			return TRUE;
	}

	// 
	// D) Ridimensionarlo
	//

	if (sDest.cy<16) 
		hdlImageNew=IMGRemaker(	hdlImage,
								&srRectSource,
								sDest.cx,
								sDest.cy,
								TRUE,
								psImgResize->iResampling);
		else
		hdlImageNew=IMGResampling(	hdlImage,
									&srRectSource,
									sDest.cx,
									sDest.cy,
									psImgResize->iResampling);
	if (hdlImageNew<0)
	{
#ifdef EH_CONSOLE
		printf("ko:%s: errore in IMGRemaker() %d",psImgResize->pszFileSource,hdlImageNew);
#endif
		ehLogWrite("%s: errore in IMGRemaker() %d",psImgResize->pszFileSource,hdlImageNew);
		memoFree(hdlImage,"Img1"); // Libero memoria immagine
		hdlImage=-1;
		return TRUE;
	}

	//
	// DX) Eseguo (eventuali) rotazioni/mirror dell'immagine 
	//
	if (psImgResize->iOrientation>1) {

		INT hdlImage;
		
		switch (psImgResize->iOrientation) {
		
			case 2: // "flip horizontal",  // left right reversed mirror
				IMGMirrorX(hdlImageNew);
				break;

			case 3: // Rotate 180
				hdlImage=IMGRotation(ROT_180,hdlImageNew);
				memoFree(hdlImageNew,"rot");
				hdlImageNew=hdlImage;
				break;

			case 4: // upside down mirror
				IMGMirrorY(hdlImageNew);
				break;

			case 5: // Flipped about top-left <--> bottom-right axis.
			case 7: // flipped about top-right <--> bottom-left axis
				IMGMirrorX(hdlImageNew);
				IMGMirrorY(hdlImageNew);
				break;

			case 6: // rotate 90 cw to right it.
				hdlImage=IMGRotation(ROT_270,hdlImageNew);
				dw=sPhotoDest.cx; sPhotoDest.cx=sPhotoDest.cy; sPhotoDest.cy=dw;
				memoFree(hdlImageNew,"rot");
				hdlImageNew=hdlImage;
				break;

			case 8: // rotate 270 to right it.
				hdlImage=IMGRotation(ROT_90,hdlImageNew);
				dw=sPhotoDest.cx; sPhotoDest.cx=sPhotoDest.cy; sPhotoDest.cy=dw;
				memoFree(hdlImageNew,"rot");
				hdlImageNew=hdlImage;
				break;
				
		}
	}

	// ------------------------------------------------------------------------
	// E) Creare un'immagine con il colore di background scelto	 
	//	  2012 release: se trasparente rimane tale
	//
	bFillBack=true;
	if (ImgHead.enPixelType!=IMG_PIXEL_RGB_ALPHA) {

		if (psImgResize->enPhotoAdatta!=IMGPT_MAX_SIDE) 
			hdlImageEnd=IMGCreate(IMG_PIXEL_RGB,"newImage",sPhotoDest.cx,sPhotoDest.cy,NULL,FALSE);
			else
			{hdlImageEnd=IMGCreate(IMG_PIXEL_RGB,"newImage",sDest.cx,sDest.cy,NULL,FALSE); bFillBack=false;}

	} else {

		if (psImgResize->enPhotoAdatta!=IMGPT_MAX_SIDE) 
			hdlImageEnd=IMGCreate(IMG_PIXEL_RGB_ALPHA,"newImage",sPhotoDest.cx,sPhotoDest.cy,NULL,FALSE);
			else
			{hdlImageEnd=IMGCreate(IMG_PIXEL_RGB_ALPHA,"newImage",sDest.cx,sDest.cy,NULL,FALSE); }
	
	}
	
	if (bFillBack) IMGFill(hdlImageEnd,psImgResize->cBackColor);

	// ------------------------------------------------------------------------
	// E2) Applico gli autolivelli se richiesto
	//

	if (psImgResize->bAutoLevel)
	{
		if (ImgHead.iChannels==3) 
		{	
			hdlImageNew=IMGAutoLevel(hdlImageNew);
		}
	}

	//
	//	Ricalcolo il posizionamento
	//
	if (psImgResize->enPhotoAdatta!=IMGPT_MAX_SIDE) {

		if (psImgResize->enPhotoAdatta) {

			RectCalcSize(	&sDest,		// Dimensioni del sorgente
							&psImgResize->sFix,			// Dimensione Area destinazione finale
							psImgResize->psMin,			// Dimensione Area destinazione finale
							psImgResize->psMax,			// Dimensione Area destinazione finale
							IMGPT_NO, // Tipo di adattamento
							psImgResize->sPhoto.iAlignHor,		// Allineamento orizzontale
							psImgResize->sPhoto.iAlignVer,		// Allineamento verticale
							&psImgResize->sDest,		// Dimensioni della destinazione
							&rDest,
							NULL); 		// Posizionamento in destinazione
			memcpy(&sDest,&psImgResize->sDest,sizeof(SIZE));

		 } else _(rDest);

		// ------------------------------------------------------------------------
		// F) Inserire il sorgente nella destinazione
		//
		ptPhoto.x=rDest.left+psImgResize->sPhoto.iOffsetX;
		ptPhoto.y=rDest.top+psImgResize->sPhoto.iOffsetY;

	} else {ptPhoto.x=0; ptPhoto.y=0;}

	IMGCopy(hdlImageEnd, // --> La destinazione
			hdlImageNew, // <-- Il sorgente
			ptPhoto,		 // La posizione
			psImgResize->sPhoto.iAlpha);
	
	memoFree(hdlImageNew,"Img1");
	memoFree(hdlImage,"Img1"); // Libero memoria immagine
	hdlImage=-1;

	// 
	// G2) PAINT - Ping moltiplicato -------------------------------------------------------------
	//
	if (!strEmpty(psImgResize->sPaint.szFile))
	{
		INT iErr;
		INT hdlLogo=-1,hdlLogoNew=-1;
		IMGHEADER ImgLogoHead;
		SIZE sLogoDest;
		RECT rLogoDest;
//		BOOL bOffset;
		
		// a) Carico il PNG in memoria
		if (!PNGReadFile(psImgResize->sPaint.szFile,&hdlLogo,&iErr,FALSE))
		{
			printf("ko");
			printf("%s: errore in PNGReadFile() %d",psImgResize->sPaint.szFile,iErr);
			ehLogWrite("%s: errore in PNGReadFile() %d",psImgResize->sPaint.szFile,iErr);
			memoFree(hdlImageEnd,"Img2");
			return TRUE;
		}

		memcpy(&ImgLogoHead,memoLock(hdlLogo),sizeof(IMGHEADER));
		memoUnlockEx(hdlLogo,"A3");

		if (psImgResize->sPaint.psSizeFix) {

			memcpy(&sLogoDest,psImgResize->sLogo.psSizeFix,sizeof(SIZE));

		} else {
			sLogoDest.cx=(INT) (ImgLogoHead.bmiHeader.biWidth*psImgResize->sPaint.dPerc/100);
			sLogoDest.cy=(INT) (ImgLogoHead.bmiHeader.biHeight*psImgResize->sPaint.dPerc/100);
		}

		// b) Calcolo le nuove dimensioni
		IMGCalcSize(&ImgLogoHead,      // Dimensioni del sorgente
					&sLogoDest,		   // Area disponibile
					psImgResize->psMin,
					psImgResize->psMax,
					IMGPT_AL_FORMATO,  // Tipo di adattamento
					0,	   // Allineamento orizzontale
					0,	   // Allineamento verticale
					&sLogoDest,		   // Dimensioni della destinazione
					&rLogoDest,
					&srRectLogo); 	   // Posizionamento in destinazione

		
		// c) Creo (ridimensionando) il nuovo Ping
		hdlLogoNew=IMGResampling(hdlLogo,NULL,sLogoDest.cx,sLogoDest.cy,psImgResize->iResampling);
		memoFree(hdlLogo,"Img1"); // Libero memoria immagine
		hdlLogo=-1;

		if (hdlLogoNew<0)
		{
			printf("ko");
			printf("%s: errore in IMGRemaker(LOGO) %d",psImgResize->sPaint.szFile,hdlLogoNew);
			ehLogWrite("%s: errore in IMGRemaker(LOGO) %d",psImgResize->sPaint.szFile,hdlLogoNew);
			memoFree(hdlImageEnd,"Img2");
			return TRUE;
		}
	
		// Applico
		for (ptArea.y=(psImgResize->sPaint.iOffsetY-sLogoDest.cy);ptArea.y<psImgResize->sDest.cy;ptArea.y+=sLogoDest.cy)
		{
			INT iOffset=psImgResize->sPaint.iOffsetX-sLogoDest.cx;

			for (ptArea.x=iOffset;ptArea.x<psImgResize->sDest.cx;ptArea.x+=sLogoDest.cx)
			{
				POINT ptArea2;
				// printf("Copio: %d,%d (%d)",pArea.x,pArea.y,iLogoAlpha);
				IMGCopy(hdlImageEnd,	// La destinazione
						hdlLogoNew,		// Il sorgente
						ptArea,			// La posizione
						psImgResize->sPaint.iAlpha);

				if (psImgResize->iEchoPaint)
				{
					ptArea2.x=ptArea.x+sLogoDest.cx/4;
					ptArea2.y=ptArea.y+sLogoDest.cy/4;
					IMGCopy(hdlImageEnd,	// La destinazione
							hdlLogoNew,		// Il sorgente
							ptArea2,			// La posizione
							psImgResize->sPaint.iAlpha+psImgResize->iEchoPaint);
				}
			}
		}



		// e) Libero le risorse impegnate
		memoFree(hdlLogoNew,"Logo1"); // Libero memoria immagine
	}


	// 
	// G) Fonde il Ping (se presente)
	//
	if (!strEmpty(psImgResize->sLogo.szFile))
	{
		INT iErr;
		INT hdlLogo=-1,hdlLogoResized=-1;
		IMGHEADER sImgLogoHead;
		SIZE sLogoDest;
		RECT rLogoDest;
		
		if (!PNGReadFile(psImgResize->sLogo.szFile,&hdlLogo,&iErr,FALSE))
		{
			printf("ko: %s: errore in PNGReadFile() %d",psImgResize->sLogo.szFile,iErr);
			ehLogWrite("%s: errore in PNGReadFile() %d",psImgResize->sLogo.szFile,iErr);
			memoFree(hdlImageEnd,"Img2");
			return true;
		}

		memcpy(&sImgLogoHead,memoLock(hdlLogo),sizeof(IMGHEADER));
		memoUnlockEx(hdlLogo,"A4");

		if (psImgResize->sLogo.psSizeFix) {
			
			memcpy(&sLogoDest,psImgResize->sLogo.psSizeFix,sizeof(SIZE));
		
		} else {

			if (psImgResize->sLogo.dPerc<1) psImgResize->sLogo.dPerc=100;
			if (psImgResize->sLogo.bPosWhere) // Posiziono con riferimento alla foto
			{
				sLogoDest.cx=(INT) (sDest.cx*psImgResize->sLogo.dPerc/100);
				sLogoDest.cy=(INT) (sDest.cy*psImgResize->sLogo.dPerc/100);
			
			}
			else {
				sLogoDest.cx=(INT) (psImgResize->sDest.cx*psImgResize->sLogo.dPerc/100);
				sLogoDest.cy=(INT) (psImgResize->sDest.cy*psImgResize->sLogo.dPerc/100);
			}
		}
		
		//
		// Se serve ridimensiono il logo
		//
		if (sImgLogoHead.bmiHeader.biWidth!=sLogoDest.cx||
			sImgLogoHead.bmiHeader.biHeight!=sLogoDest.cy) {

				// b) Calcolo le nuove dimensioni
				IMGCalcSize(&sImgLogoHead,      // Dimensioni del sorgente
							&sLogoDest,		   // Area disponibile
							NULL,
							NULL,
							IMGPT_AL_FORMATO,  // Tipo di adattamento
							0,	   // Allineamento orizzontale
							0,	   // Allineamento verticale
							&sLogoDest,		   // Dimensioni della destinazione
							&rLogoDest,
							&srRectLogo); 	   // Posizionamento in destinazione

				// c) Creo (ridimensionando) il nuovo Ping
				
				if (sLogoDest.cy<16) 
					hdlLogoResized=IMGRemaker(hdlLogo,NULL,sLogoDest.cx,sLogoDest.cy,TRUE,psImgResize->iResampling);
					else
					hdlLogoResized=IMGResampling(hdlLogo,NULL,sLogoDest.cx,sLogoDest.cy,psImgResize->iResampling);

				memoFree(hdlLogo,"Img1"); // Libero memoria immagine
				hdlLogo=-1;
		} else {

			hdlLogoResized=hdlLogo;
			hdlLogo=-1;
		
		}

		if (hdlLogoResized<0)
		{
			printf("ko");
			printf("%s: errore in IMGRemaker(LOGO) %d",psImgResize->sLogo.szFile,hdlLogoResized);
			ehLogWrite("%s: errore in IMGRemaker(LOGO) %d",psImgResize->sLogo.szFile,hdlLogoResized);
			memoFree(hdlImageEnd,"Img2");
			return TRUE;
		}
	

		// 
		// Allineamento Orizzontale
		//
		switch (psImgResize->sLogo.iAlignHor)
		{
			case 1: // Left
				if (psImgResize->sLogo.bPosWhere) ptArea.x=rDest.left; else ptArea.x=0; 
				break;

			case 2: // Right
				if (psImgResize->sLogo.bPosWhere) 
						ptArea.x=rDest.right-sLogoDest.cx;
						else
						ptArea.x=psImgResize->sDest.cx-sLogoDest.cx;
				break;

			default:
			case 0: // Centra (Default)
//				pArea.x=((psImgResize->sDim.cx-sLogoDest.cx)/2);
				ptArea.x=rDest.left+((sDest.cx-sLogoDest.cx)/2);
				break;
		}

		// 
		// Allinamento Verticale
		//
		switch (psImgResize->sLogo.iAlignVer)
		{
			case 1: // Top
				if (psImgResize->sLogo.bPosWhere) ptArea.y=rDest.top; else ptArea.y=0;
				break;

			case 2: // Bottom
				if (psImgResize->sLogo.bPosWhere) ptArea.y=rDest.bottom-sLogoDest.cy; else ptArea.y=sPhotoDest.cy-sLogoDest.cy; // C'era un +1 cazzo
				break;

			default:
			case 0: // Centra (Default)
//				pArea.y=((psImgResize->sDim.cy-sLogoDest.cy)/2);
				ptArea.y=rDest.top+((sDest.cy-sLogoDest.cy)/2);
				break;
		}
		
		ptArea.x+=psImgResize->sLogo.iOffsetX;//iLogoOffsetX;
		ptArea.y+=psImgResize->sLogo.iOffsetY;//iLogoOffsetY;

		// printf("Copio: %d,%d (%d)",pArea.x,pArea.y,iLogoAlpha);
		IMGCopy(hdlImageEnd, // La destinazione
				hdlLogoResized, // Il sorgente
				ptArea,		 // La posizione
				psImgResize->sLogo.iAlpha); //(double) 100);//psImgResize->sLogo.iAlpha);  <-- da controllare il valore dell' alpha

//		if (strstr(psImgResize->pszFileDest,"\\big"))
//			printf("qui");

		// e) Libero le risorse impegnate
		memoFree(hdlLogoResized,"Logo1"); // Libero memoria immagine
	}


	//
	// Se ho dei comandi di testo li processo
	//
	if (!strEmpty(psImgResize->lpText)) TextProcessor(hdlImageEnd,psImgResize->lpText);


	// ------------------------------------------------------------------------
	// H) Salvare l'immagine
	//
	if (!psImgResize->enImageTypeSave) psImgResize->enImageTypeSave=IMG_JPEG; // Per compatibilità con il passato
	switch (psImgResize->enImageTypeSave)
	{
		case IMG_PNG:
			iErr=PNGSaveFile(psImgResize->pszFileDest,hdlImageEnd,psImgResize->iQuality);
			break;

		case IMG_JPEG:
			iErr=JPGSaveFile(psImgResize->pszFileDest,hdlImageEnd,psImgResize->iQuality);
			break;
		
		default:
			ehError();
			break;

	}

	memoFree(hdlImageEnd,"Img2");
	if (!iErr)
	{
#ifdef EH_CONSOLE
		printf("ko:%s: errore in JPGSave() %d",psImgResize->pszFileDest,iErr);
#endif
		ehLogWrite("%s: errore in JPGSave() %d",psImgResize->pszFileDest,iErr);
		return TRUE;
	}

 //printf("ok");
 return FALSE;
}
Example #3
0
//
// Driver Odbc
//
void *	sqlLiteScroll(struct OBJ *objCalled,EN_MESSAGE cmd,LONG info,CHAR *str)
{
	static struct WINSCR rit,*PtScr;
	EH_DISPEXT *psExt;
	
    S_SCR_INFO * psSI,sSqlInfo;
	INT   a;//,b;
//	INT   ptClient;
//	SQLRETURN sqlReturn;

	//
	// Inizializzazione
	//
	if (_local.bReset)
	{
		_local.lstScr=lstCreate(sizeof(S_SCR_INFO));
		 FTIME_on(_SqlThreadRefresh,1);
		_local.bReset=false;
	}

	// Oggetto buono ?
	if ((objCalled->tipo!=OW_SCR)&&(objCalled->tipo!=OW_SCRDB)) return 0;

	psSI=objCalled->pOther;
	if (cmd==WS_INF) return &psSI->ws;

	switch (cmd) 
	{
	// -----------------------------------
	// APERTURA DEL DRIVER               |
	// -----------------------------------

		case WS_CREATE: //break;

#ifdef OS_DEBUG
			printf("OdbcScroll: Create" CRLF);
#endif

			_(sSqlInfo);
			objCalled->pOther=lstPush(_local.lstScr,&sSqlInfo);
			psSI=objCalled->pOther;
			psSI->ObjClient=objCalled;
			psSI->ObjClient->bFreeze=TRUE; // Blocco la gestione dell'oggetto
			psSI->bDrawLineDiv=TRUE;
#ifdef EH_SQL_SQLITE
			psSI->enPlatform=_SQL_SQLITE;
#endif
#ifdef EH_SQL_MYSQL
			psSI->enPlatform=_SQL_MYSQL;
#endif

			//
			// Alla prima chiamata creo thread e "finestrame" necessario 
			// 

			// Tecnologia sqlLite
			//		- La connessione deve essere inizializzata
			//
			if (!psSI->hThread)
			{
				memset(&psSI->csSqdStruct,0,sizeof(CRITICAL_SECTION));
				memset(&psSI->csSqdQuery,0,sizeof(CRITICAL_SECTION));
				InitializeCriticalSection(&psSI->csSqdStruct); 
				InitializeCriticalSection(&psSI->csSqdQuery); 
/*
			
				// 
				// Alloco lo stantment clone ( Si libererà con WS_DESTROY)
				//
				sqlReturn=SQLAllocHandle(SQL_HANDLE_STMT, sOdbcSection.hConn, &psSI->hStmtScroll);
				if (sqlReturn!=SQL_SUCCESS&&sqlReturn!=SQL_SUCCESS_WITH_INFO) ehExit("OdbcScroll:hStmt Clone impossible %d",sqlReturn);

				// Bho ?
				SQLSetStmtAttr(psSI->hStmtScroll, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_READ_ONLY, 0);

				sqlReturn=SQLSetStmtAttr(psSI->hStmtScroll, SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE , 0);
				if (sqlReturn==SQL_ERROR)  
				// Altro metodo
				{
					sqlReturn=SQLSetStmtAttr( psSI->hStmtScroll,SQL_ATTR_CURSOR_TYPE,  (SQLPOINTER) SQL_CURSOR_STATIC, 0);
					if (sqlReturn==SQL_ERROR) win_infoarg("errore in assegnazione cursore");
					sqlReturn=SQLSetStmtAttr( psSI->hStmtScroll, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER) SQL_UB_VARIABLE, 0);
					if (sqlReturn==SQL_ERROR) win_infoarg("SQL_ATTR_USE_BOOKMARKS");
				}

				//sprintf(szCursor,"SQD%d",ptClient);
				//SQLTRY(SQL_HANDLE_STMT,"SQD->",psSI->hStmtScroll,SQLSetCursorName(psSI->hStmtScroll, szCursor, SQL_NTS));
				//SQLTRY("ASYNC",psSI->hStmtScroll,SQLSetStmtAttr(psSI->hStmtScroll, SQL_ATTR_ASYNC_ENABLE, (SQLPOINTER) SQL_ASYNC_ENABLE_ON , 0));


				//
				// 4) Creo il Thread (SQLExecuteThread) per l'elaborazione delle query
				//
				*/
				for (a=0;a<ESQL_MAXEVENTLOAD;a++) psSI->arhEvent[a]=CreateEvent(NULL,true,FALSE,NULL); 
				psSI->hThread = CreateThread(NULL, 
											  0, 
											  _sqlExecuteThread, 
											  (LPDWORD) psSI,
											  0, 
											  &psSI->dwThread);
				psSI->bAutoRowSelect=TRUE; // <-- 2010 - Inserito auto select in partenza
				SetThreadPriority(psSI->hThread,THREAD_PRIORITY_NORMAL);
			}
			break;

		case WS_OPEN:

		//
		//	Inizializzazione della finestra
		//	
			if (info<3) {ehExit("Field ? " __FUNCTION__);}
			psSI->ws.numcam=info;// Assegna il numero di campi da visualizzare
			psSI->ws.selez=-1; 
			psSI->ws.maxcam=0;
			psSI->ObjClient->tipo=OW_SCR;
			psSI->lRowsTotal=0;
			psSI->fChanged=0;
			psSI->ObjClient->bFreeze=FALSE;

			if (psSI->funcNotify) psSI->funcNotify(_adaptor(objCalled,WS_OPEN,0,NULL,NULL));//objCalled,NULL,0,NULL,WS_OPEN,NULL,NULL);
			psSI->ws.bExtSelection=TRUE; // Gestione esterna della selezione
			psSI->ws.fNoBlankLine=TRUE;
			

		case WS_LOAD:  
			break;

	// -----------------------------------
	// Richiesta di refresh
	// -----------------------------------
	case WS_RELOAD: 
			if (info)
				_queryExecute(psSI,__LINE__); 
				else
				_fetch(psSI); 
				
			return NULL; // Non serve stampare

	// -----------------------------------
	// WS_CLOSE IL DRIVER                  |
	// -----------------------------------
	case WS_CLOSE:
			sqlLiteScroll(objCalled,WS_PROCESS,STOP,NULL); // Chiedo di fermare il processo in corso
			psSI->ObjClient->bFreeze=true;
			if (psSI->funcNotify) (psSI->funcNotify)(_adaptor(objCalled,WS_CLOSE,0,NULL,NULL));
			break;

	// -----------------------------------
	// CHIUSURA DEFINITIVA DEL GESTORE (chiamato in obj_close());
	// -----------------------------------
	case WS_DESTROY: 

			//
			// Notifico la chiusura alla funzione esterna
			//
			if (psSI->funcNotify) (psSI->funcNotify)(_adaptor(objCalled,WS_DESTROY,0,NULL,NULL));

			// Fermo il Thread
			SetEvent(psSI->arhEvent[ESQL_STOP]); // Segnalo che siamo in chiusura
			if (WaitForSingleObject(psSI->hThread,5000)) 
			 {
				//_dx_(0,20,"Entro qui");
				//SQLFetchScroll(psSI->hStmtScroll,SQL_FETCH_FIRST,0);
				//SQLFreeHandle(SQL_HANDLE_STMT,psSI->hStmtScroll); psSI->hStmtScroll=0;
				//_dx_(0,40,"Terminate %d",TerminateThread(psSI->hThread,0));
			 }

			/*
			 if (psSI->hStmtScroll) {SQLFreeHandle(SQL_HANDLE_STMT,psSI->hStmtScroll); psSI->hStmtScroll=0;}
			 if (psSI->rsSet) {odbc_QueryResultDestroy(psSI->rsSet); ehFree(psSI->rsSet);}
			 psSI->rsSet=NULL;

			 // Libero la memoria usata per la Query
			 ehFreePtr(&psSI->pQueryActive);
			 ehFreePtr(&psSI->pszQueryCount);
			 ehFreePtr(&psSI->pLastErrorText);

			 // Libero la memoria usata per la WhereAdd
			 ehFreePtr(&psSI->pQuerySelect);

			 ehFreePtr(&psSI->pszKeyCode);
			 ARDestroy(psSI->arKeyCodeFld);
			 ehFreePtr(&psSI->pCodeFocused);
			 ehFreePtr(&psSI->pCodeSelected);
			 ehFreePtr(&psSI->pCodeReturn);

			 // Libero gli Handle degli eventi
			 for (a=0;a<ESQL_MAXEVENTLOAD;a++) CloseHandle(psSI->arhEvent[a]);

			 // 1.2.3. Liberi tutti !!
			 DeleteCriticalSection(&psSI->csSqdStruct); 
			 DeleteCriticalSection(&psSI->csSqdQuery); 
			 // Azzero la struttura di riferimento
			 memset(psSI,0,sizeof(S_SCR_INFO));
			 */
			{
				EH_LST_I * psi;
				psi=lstSearch(_local.lstScr,objCalled->pOther);
				lstRemoveI(_local.lstScr,psi);
			}
			 ehFreePtr(&objCalled->pOther);
			 break;

	// -----------------------------------
	// PRESSIONE DI UN TASTO/MOUSE       |
	// -----------------------------------
	case WS_KEYPRESS:
			if (key_press2(KEY_F9)) {strcpy(str,"ESC:F9"); break;}
			if (psSI->funcNotify) (psSI->funcNotify)(_adaptor(objCalled,cmd,info,str,NULL)); 
			break;

	// -----------------------------------
	// SETTA SELEZIONE RECORD            |
	// -----------------------------------
	case WS_SEL: 
			if (!psSI->funcNotify) break;//ehExit(SdbDriver32 ":No ext/disp function");
			// if (!psSI->rsSet) break;
			// printf("%d",psSI->rsSet->iCurrentRow);
			//if (psSI->ws.selez==-1) break;
			break;

	// -------------------------------------
	// SETTA L'OFFSET  (Solo Modo O_SCROLL |
	// -------------------------------------
	case WS_OFF: break;

	// -------------------------------------
	// 
	// -------------------------------------
	case WS_PTREC : //			  			Restituisce pt alla chiave selezionata
	case WS_GET_SELECTED:

			_(rit);
			rit.record=-1;

			if (strEmpty(psSI->pszKeyCode)) {efx2(); return NULL;}
			/*
			//
			// Selezione in scroll
			//
			if (psSI->rsSet&&psSI->ws.selez>-1)
			{
				psSI->rsSet->iCurrentRow=psSI->ws.selez;
				if (strEmpty(psSI->pszKeyCode)) ehExit("%s:%d manca assegnazione pszKeyCode",__FILE__,__LINE__);
				_keyCodeBuilder(&psSI->pCodeReturn,psSI);

				rit.record=psSI->ws.selez;
				rit.keypt=psSI->pCodeReturn;
				if (psSI->bAutoRowSelect)
				{
					strAssign(&psSI->pCodeSelected,psSI->pCodeReturn);
					InvalidateRect(objCalled->hWnd,NULL,FALSE);
				}
			}
			//
			// Pre-selezione (non entrao in scroll
			//
			else if (!strEmpty(psSI->pCodeSelected)) {

				rit.record=psSI->ws.selez;
				rit.keypt=psSI->pCodeSelected;
			}
			if (cmd==WS_GET_SELECTED) return retCreate(_ALFA,rit.record,rit.keypt);
			*/
			return &rit;

	// -------------------------------------
	// RITORNA Selez ??????????            |
	// -------------------------------------
	case WS_REALGET:
			 break;

	// -------------------------------------
	// Refresh a ON                        |
	// -------------------------------------
	case WS_REFON : psSI->ws.refre=ON; break;
	case WS_REFOFF : psSI->ws.refre=OFF; break;

	case WS_PROCESS:
		if (info==STOP&&!str)
		 {
			// SQLCancel(psSI->hStmtScroll); // Cancello il processo nello stantment
			 printf("> cancellare processo in corso");
			EnterCriticalSection(&psSI->csSqdStruct);
			psSI->fBreak=true;
			LeaveCriticalSection(&psSI->csSqdStruct);
			while (TRUE) {if (!psSI->fInProcess) break; else Sleep(50);}
			//win_infoarg("SQL stop");
		}
		// Controllo se l'elaborazione è in corso
		if ((info==0)&&(*str=='?'))
		{
		  if (psSI->fInProcess) return "!"; else return NULL;
		}
		break;

	
	// 
	// Chiedo di cambiare il la Where di ricerca
	//
	case WS_SETFILTER:

		EnterCriticalSection(&psSI->csSqdStruct);
		ehFreePtr(&psSI->pQuerySelect); 
	 	psSI->pQuerySelect=strDup(str);
		psSI->ws.selez=-1;
		psSI->ws.maxcam=0;
		psSI->lRowsReady=0;
		psSI->lRowsTotal=0;
		LeaveCriticalSection(&psSI->csSqdStruct);
		if (info)
		{
			InvalidateRect(objCalled->hWnd,NULL,TRUE);
			_message(psSI,TRUE,"Attendere\nRichiesta al server ...");
			OsEventLoop(5);
		}
		psSI->fQueryToExecute=true;
		// _queryExecute(psSI,__LINE__); // Me ne arriva uno dopo
		break;

	case WS_SETFLAG:
		objCalled->pOtherEx=str; // Assegno un puntatore esterno
		if (psSI->funcNotify) (psSI->funcNotify)(_adaptor(objCalled,WS_SETFLAG,info,NULL,NULL)); 
		break;

	// -------------------------------------
	// Richiesta di Stampa dei Dati        |
	// -------------------------------------
	case WS_DISPLAY : //			  			Richiesta buffer
			 
			psExt=(EH_DISPEXT *) str;

			if (!psSI->funcNotify) {
				Tboxp(	psExt->rClientArea.left,
						psExt->rClientArea.top,
						psExt->rClientArea.right,
						psExt->rClientArea.bottom-1,
						RGB(255,128,0),SET);
//						arError=ARCreate(psSI->pLastErrorText,"\n",&iRow);
				dispf(psExt->px+1,psExt->py+1,RGB(255,255,255),-1,STYLE_NORMAL,"SMALL F",3,"-Not func for Display-");
				break;
			}

			//
			// Richiesta di stampa del titolo
			//
			if (psExt->ncam==-10) 
			{
				psSI->funcNotify(_adaptor(objCalled,WS_DISPLAY,0,psExt,NULL));//psSI->Hdb,psSI->iIndex); 
				break;
			}
/*
			if (!psSI->rsSet) 
			{
				if (psSI->bSqlError)
				{
					Tboxp(psExt->px,psExt->py,psExt->px+psExt->lx-1,psExt->py+psExt->ly-1,sys.Color3DShadow,SET);
					if (psSI->pLastErrorText)
					{
						EH_AR arError;
						INT iRow;
						arError=ARCreate(psSI->pLastErrorText,"\n",&iRow);
						if (psExt->ncam<iRow) dispf(psExt->px+1,psExt->py+1,RGB(255,255,255),-1,STYLE_NORMAL,"SMALL F",3,arError[psExt->ncam]);
						ARDestroy(arError);
					}
				}
				else
				Tboxp(psExt->px,psExt->py,psExt->px+psExt->lx-1,psExt->py+psExt->ly-1,sys.Color3DLight,SET);
				break;
			 }

			 psExt->col1=GetSysColor(COLOR_MENUTEXT); 
			 psExt->col2=GetSysColor(COLOR_WINDOW);

			 if (psExt->bFocus) // selezione con il mouse
				{
					psExt->col1=GetSysColor(COLOR_HIGHLIGHTTEXT); 
					psExt->col2=ColorLum(GetSysColor(COLOR_HIGHLIGHT),30);
				} 

			 if (psExt->bSelected) // Selezionato fisso
				{
					psExt->col1=GetSysColor(COLOR_HIGHLIGHTTEXT); 
					psExt->col2=GetSysColor(COLOR_HIGHLIGHT); 
				} 

			Tboxp(psExt->px,psExt->py,psExt->px+psExt->lx-1,psExt->py+psExt->ly-2,psExt->col2,SET); //Sleep(100);

			psSI->rsSet->iCurrentRow=info;
			psSI->rsSet->iOffset=psSI->iSQLOffset;

			// Non ho ancora le linee da visualizzare
			if (psExt->ncam>=psSI->lRowsReady||
				(psSI->rsSet->iCurrentRow<psSI->iSQLOffset)||
				((psSI->rsSet->iCurrentRow-psSI->iSQLOffset)>=psSI->rsSet->iRowsLimit)) 
			{
				boxBrush(psExt->px,psExt->py,psExt->rClientArea.right,psExt->rClientArea.bottom,HS_VERTICAL,sys.Color3DLight,ColorLum(sys.Color3DHighLight,-10));
				Tline(psExt->px,psExt->rClientArea.bottom,psExt->rClientArea.right,psExt->rClientArea.bottom,sys.Color3DShadow,SET);
				break;
			}

			// RIchiedo stampa della riga
			psSI->funcNotify(	_adaptor(objCalled,WS_DISPLAY,info,psExt, psSI->rsSet));

			if (psSI->bDrawLineDiv) line(psExt->px,psExt->rClientArea.bottom,psExt->rClientArea.right,psExt->rClientArea.bottom,sys.colScrollDiv,SET);
			if (psExt->bFocus) 
			{
				boxFocus(psExt->px,psExt->py,psExt->px+psExt->lx-1,psExt->py+psExt->ly-2);
			}
			*/
			break;

	// --------------------------------------------------------------------------
	// SET della funzione esterna
	// --------------------------------------------------------------------------
	case WS_EXTNOTIFY: 
			 psSI->funcNotify=(LRESULT (*)(EH_NOTIFYPARAMS)) str;//(INT (*)(struct OBJ *,INT ,LONG  ,void  *str,EH_ODBC_RS )) str;
			 psSI->funcNotify(_adaptor(objCalled,WS_CREATE,0,NULL,NULL));
			 break;

	case WS_LINEVIEW: //	 
		psSI->ws.numcam=info;
		break;

	case WS_LINEEDIT: //	 
		psSI->ws.Enumcam=info;
		break;

	case WS_SIZE: break;
	case WS_MOVE: break;

	case WS_SETTITLE: break;
	case WS_CODENAME: 
		
		strAssign(&psSI->pszKeyCode,str); strTrim(psSI->pszKeyCode); 
		ARDestroy(psSI->arKeyCodeFld);
		psSI->arKeyCodeFld=ARCreate(psSI->pszKeyCode,"+",&psSI->iKeyCodePart);
		break;

	//
	// Riga in FOCUS
	//
		/*
	case WS_SET_ROWFOCUS: 
			if (!str) // Dal gestore oggetti
			{
				 if (info<0) {strAssign(&psSI->pCodeFocused,NULL); break;}
				 if (psSI->pCodeName&&psSI->rsSet)
				 {
					psSI->rsSet->iCurrentRow=info;
					psSI->rsSet->iOffset=psSI->ws.offset;

					// psSI->rsSet->iCurrentRow riga della query

					if (psSI->rsSet->iCurrentRow>=psSI->iSQLOffset&&
						psSI->rsSet->iCurrentRow<(psSI->iSQLOffset+psSI->lRowsReady))
					{
						strAssign(&psSI->pCodeFocused,sql_ptr(psSI->rsSet,psSI->pCodeName));
						strTrim(psSI->pCodeFocused);
					}
					else
					{
						strAssign(&psSI->pCodeFocused,NULL); // Non ho la selezione richiesta in memoria
					}
					dispxEx(0,80,"%d,%d = %s          ",
							psSI->rsSet->iCurrentRow,
							psSI->iSQLOffset+psSI->lRowsReady,
							psSI->pCodeFocused);
				 }
				return NULL;
			}
			else // Esterno
			{
				strAssign(&psSI->pCodeFocused,str);
				InvalidateRect(objCalled->hWnd,NULL,FALSE);
			}
			break;

	case WS_GET_ROWFOCUS: 
			 if (psSI->pCodeName&&psSI->pCodeFocused&&psSI->rsSet)
			 {
				CHAR *p;
				if (info<0) return NULL;
				psSI->rsSet->iCurrentRow=info;
				psSI->rsSet->iOffset=psSI->ws.offset;

				p=sql_ptr(psSI->rsSet,psSI->pCodeName); strTrimRight(p);
				if (!strcmp(p,psSI->pCodeFocused)) break;
			 }
			 return NULL;
*/

	//
	// Riga in SELECTED
	//
	case WS_SET_ROWSELECTED: 
			printf("qui");
		/*
			 if (!str) // Dal gestore oggetti
			 {
				 if (info<0) {strAssign(&psSI->pCodeSelected,NULL); InvalidateRect(objCalled->hWnd,NULL,FALSE); break;}
				 if (psSI->pszKeyCode&&psSI->rsSet)
				 {
					psSI->rsSet->iCurrentRow=info;
					psSI->rsSet->iOffset=psSI->ws.offset;
					_keyCodeBuilder(&psSI->pCodeSelected,psSI); //if (!strEmpty(p)) break;
				 }
				InvalidateRect(objCalled->hWnd,NULL,FALSE);
				return NULL;
			}
			else // Esterno
			{
				strAssign(&psSI->pCodeSelected,str);
				InvalidateRect(objCalled->hWnd,NULL,FALSE);
			}
			*/
			break;

	case WS_GET_ROWSELECTED: 

			//
			// Controllo di selezione
			// 
			if (psSI->pszKeyCode&&!strEmpty(psSI->pCodeSelected)&&psSI->rsSet)
			 {
				 CHAR * p;
				if (info<0) return NULL;

				//psSI->rsSet->iCurrent=info;
				p=_keyCodeBuilder(psSI,info); // Può ritornare Null in p se sto chiedendo una riga che non c'è (in fase di ingrandimento)
				if (!strCmp(p,psSI->pCodeSelected)) {ehFreeNN(p); break;}
				ehFreeNN(p); 
			 }
			 return NULL;

	case WS_EVENT:
		/*
			if (!psSI->rsSet) break;
			psSI->rsSet->iCurrentRow=info;
			psSI->rsSet->iOffset=psSI->iSQLOffset;
			if (psSI->funcNotify) 
			{
				BYTE *ptr=(BYTE *) (psSI->funcNotify)(_adaptor(objCalled,cmd,info,str,psSI->rsSet));
				return ptr;
			}
			*/
			printf("qui");
			break;

	case WS_BUF:
			break;

	default:
/*
		if (psSI->funcNotify) 
			(psSI->funcNotify)(_adaptor(objCalled,cmd,info,str,psSI->rsSet));
			else
			printf(__FUNCTION__ "Event ? [%d][%s]" CRLF,cmd,objCalled->nome); 
			*/
			break;
	}

	//PtScr=psSI->WinScr; 
	PtScr=NULL;
	if (!PtScr) PtScr=&rit;
	return PtScr;
}
Example #4
0
//
// ehTranslate()
//
UTF8 * ehTranslate(	ET_PARAM	enParam,
					UTF8 *		pszSource,
					CHAR *		pszLangSource,
					CHAR *		pszLangDest,
					CHAR *		pszJsonParams,	// {googlekey:"asda", bingkey:"asd"}
					ET_REPORT * psReport,
					void *		(* extAssist)(EN_MESSAGE enMess,LONG lParam,void *pVoid),
					EH_LST		lstBlackKey
					)

{
	WCHAR *pw;
	BYTE *pTradotto=NULL;
	S_PHRASES * psPh=NULL;
	S_PHSTR * psPhs;
	//INT f;
	BOOL bError=FALSE;
	INT iLen;
	INT iCharsBad;
	BYTE *pUtf;
	CHAR szLangDetect[20]="";
	double dRap;
	INT iWords;
	ET_REPORT sReportTemp;
	EH_JSON * psJson=NULL;
	CHAR * pszUserIp=NULL;
	INT		iMaxPhrases=0;
	ET_BLACK_ITEM sBlack;
	
	if (lstBlackKey) {
	
		if (lstBlackKey->iSize!=sizeof(ET_BLACK_ITEM)) ehExit("Usare transBlackListCreate();");
	}

	if (!_s.bReady) {_(_s); _s.bReady=true; ehAddExit(_transEndPoint);} // <-- Resetto la struttura Privata

	if (!psReport) psReport=&sReportTemp;
	memset(psReport,0,sizeof(ET_REPORT));

	if (!(enParam&ET_TRY_LOCAL)) extAssist=NULL;

	if (!pszLangSource) ehError();
	strcpy(psReport->szLangSource,pszLangSource);
	if (!pszLangDest) ehError();
	strcpy(psReport->szLangDest,pszLangDest);

	//
	// Assistente: ricerco prima in cache la frase completa
	//
	strTrim(pszSource);
	if (!*pszSource) {
		return strDup("");
	}

	if (enParam&ET_STAT) {
		psReport->dwChars=strlen(pszSource);
		psReport->dwWords=strWordCount(pszSource);
	}
	if (!(enParam&ET_TRANS)&&!(enParam&ET_LANGDETECT)) return NULL; // Nessun servizio richiesto

	if (pszJsonParams) {
		CHAR * psz;
		psJson=jsonCreate(pszJsonParams);
		psz=jsonGet(psJson,"maxPhrases");
		if (psz) iMaxPhrases=atoi(psz);
	}

	//
	// PREPARAZIONE FRASI DA RICHIEDERE
	// A seconda del servizio esterno di traduzione creo le frasi richieste
	//
	psPh=_phraseCreate(pszSource,iMaxPhrases);//,TTE_BING); 
	
	if (!psPh) {
		psReport->etError=GE_STRING_TOO_LONG;
		return NULL;
	}

	//
	// Richiesta traduzioni frasi
	//
	if (enParam&ET_OUTPUTDETT) {
		if (psPh->iPhraseToTrans>1) 
			printf("%s|%d}",pszLangDest,psPh->iPhraseToTrans);
			else
			printf("%s}",pszLangDest);
	}

	if (iMaxPhrases&&psPh->iPhraseToTrans>iMaxPhrases) {
	
		psReport->etError=GE_TOO_PHRASES;
		_phraseDestroy(psPh);
		jsonDestroy(psJson);
		return NULL;

	}
	if (enParam&ET_OUTPUTDETT) printf("|Phrase: total %d, problems %d, html:%d|" CRLF,psPh->iPhraseToTrans,psPh->iPhraseProblems,psPh->psTag->bHtml);
	if (enParam&ET_DOT_PROGRESS) printf("%d",psPh->iPhraseToTrans);

	//for (f=0;psPh->arPhrase[f];f++)
	for (lstLoop(psPh->lstPhrase,psPhs))
	{
		CHAR *	pszPhrase;
		CHAR *	pszPrefix=NULL;

		if (!psPhs->bTranslate) continue;

		// strTrim(psPhs->pszStr); 
		pszPhrase=psPhs->pszStr;
		if (strEmpty(pszPhrase)) continue;
		iLen=strlen(pszPhrase); if (iLen<2) continue; // Non traduco frasi con meno di 2 caratteri

		//
		// a. Controllo se è un numero
		//
 		if (!_isNaN(pszPhrase)) {ehFreePtr(&pszPrefix); continue;}

		//
		// b. Conto le parole
		//
		iWords=0; iCharsBad=0; dRap=0;
		if (enParam&ET_LANGDETECT) {

			iWords=strWordCount(pszPhrase);

			// Precontrollo stringa
			// Proporzione: iCharsBad:iLen=x:100
			iCharsBad=strCount(pszPhrase,".()[],-*_");
			dRap=iCharsBad*100/iLen;
			if (dRap>50) // Frase composta da oltre il 50% di simboli e non di lettere
			{
				psReport->etError=GE_STRING_SUSPECT; // L'indicazione della lingua sorgente è errata
				psPh->iPhraseProblems++;
				if (enParam&ET_OUTPUTDETT) printf("?");
				ehFreePtr(&pszPrefix); 
				continue;
			}
		}

		//
		// Local request ###########################################################################################
		//
		pUtf=NULL;

		if (extAssist) {

			S_TRANSLATION sTrans;

			sTrans.pszLangSource=pszLangSource;
			sTrans.pszLangDest=pszLangDest;
			sTrans.utfSource=pszPhrase;
			sTrans.utfDest=NULL;
			if (extAssist(WS_FIND,0,&sTrans)) {
				psReport->iLocalResponse++;
				if (enParam&ET_STAT) {
					psReport->dwLocalChars+=strlen(pszPhrase);
					psReport->dwLocalWords+=strWordCount(pszPhrase);
				}
				pUtf=sTrans.utfDest;
				if (pUtf) {
					psReport->enTech=ET_LOCAL;
					if (enParam&ET_SERVICE_CALL) printf("l$");
					if (enParam&ET_OUTPUTDETT) printf("l");
				}
			}
		}

		
		//
		// BING request ###########################################################################################
		//
		if (!pUtf&&
			psJson&&
			enParam&ET_TRY_BING) {
			
			CHAR * pszBingApp;
			INT iRequestDone=0;
			EH_LST lstKey;
			
			// Cerco Appi o multi Appid
			lstKey=lstNew();
			pszBingApp=jsonGet(psJson,"bingAppId");
			if (pszBingApp) lstPush(lstKey,pszBingApp);
			else {
			
				pszBingApp=jsonGet(psJson,"arBingAppId.length");
				if (pszBingApp) {
					INT a,iLen=atoi(pszBingApp);
					for (a=0;a<iLen;a++) {

						lstPush(lstKey,jsonGetf(psJson,"arBingAppId[%d]",a));

					}
				
				}
			}

			if (enParam&ET_OUTPUTDETT) printf("|pszBingApp:%s|" CRLF,pszBingApp);
			if (lstKey->iLength) {

				CHAR * pszAppId;
				if (enParam&ET_STAT) {

					psReport->dwBingChars+=strlen(pszPhrase);
					psReport->dwBingWords+=strWordCount(pszPhrase);

				}
				for (lstLoop(lstKey,pszAppId)) {

					if (_isBlackList(lstBlackKey,ET_BING,pszAppId)) continue;

					pUtf=_bingCall(		enParam,
										pszPhrase,
										pszLangSource,
										pszLangDest,
										pszAppId,
										&iRequestDone,
 										&psReport->etError); 

					if (enParam&ET_OUTPUTDETT) {
						printf("(%s) > (%s) #%d",pszPhrase,pUtf,psReport->etError);
					}
					psReport->iBingRequest+=iRequestDone;
					if (!strEmpty(pUtf)) 
						{	
							psReport->enTech=ET_BING;
							psReport->iBingResponse++; 
							if (enParam&ET_OUTPUTDETT) printf("B");
							break;
						}
						else
						{
							psReport->iBingErrors++; if (enParam&ET_OUTPUTDETT) printf("Bx");
							ehSleep(1000);
						}

					//
					// Abuso + BlackList
					//
					if (psReport->etError==GE_ABUSE&&
						lstBlackKey) {
					
							_(sBlack);
							sBlack.enTech=ET_BING;
							sBlack.pszAppId=strDup(pszAppId);
							lstPush(lstBlackKey,&sBlack);
					}
				}
			}
			lstDestroy(lstKey);
		}
Example #5
0
S_PHRASES * _phraseCreate(UTF8 * pszSource,INT iMaxPhrases) { //,EN_TTE enTech) {

	S_PHRASES * psPh=ehAllocZero(sizeof(S_PHRASES));
	CHAR * p;
	BOOL bFirst=true;

	//
	// Ricodifico i Tag Sensibili
	//
	psPh->psTag=tagEncode(pszSource);
	psPh->iMaxPhrases=iMaxPhrases;

	//
	// Estraggo Tag (da non tradurre) e Frasi (spezzate se necessario)
	//
	psPh->lstPhrase=lstCreate(sizeof(S_PHSTR));//ARNew();
	for (p=psPh->psTag->pszSourceTagged;*p;p++) {
	
		CHAR * pszOpen=strstr(p,TAG_START);
		S_PHSTR sPh;

		if (pszOpen) {
			CHAR * pszClose=strstr(pszOpen,TAG_END);

			//
			// Se c'è prende il primo pezzo tra l'inizio e il primo TAG di seperazione
			//
			if (bFirst&&(pszOpen-1)>psPh->psTag->pszSourceTagged) {
			
				CHAR * psz;
				psz=strTake(psPh->psTag->pszSourceTagged,pszOpen-1);
				if (!strEmpty(psz)) 
					_phraseBreak(psPh,psz);
				ehFree(psz); 
			}
			bFirst=false;

			if (pszClose) {

				//
				// Alloca il tag di separazione
				//
				_(sPh);
				sPh.bTranslate=false;
				sPh.pszStr=strTake(pszOpen,pszClose);
				lstPush(psPh->lstPhrase,&sPh); 

				//
				// Cerco il pezzo dopo (spezzo la stringa)
				//
				pszOpen=strstr(pszClose+1,TAG_START);
				if (pszOpen) {
				
					CHAR * psz;
					psz=strTake(pszClose+1,pszOpen-1);
					if (!strEmpty(psz)) 
						_phraseBreak(psPh,psz);
					p=pszClose+strlen(psz);
					ehFree(psz);

				} else { // Ultima stringa

					_phraseBreak(psPh,pszClose+1);
					p=pszClose+strlen(pszClose+1);
				}
				
			}
		} else {
			
			_phraseBreak(psPh,p);
			break;		
		}

	}

//
//	psPh->iPhraseTotal=ARLen(psPh->arPhrase);
	if (psPh->iSeveralError) {
		psPh=_phraseDestroy(psPh);
	} else {
	
		S_PHSTR * psPhs;
	//
	// Post controlli, creo testa e coda
	//	
		for (lstLoop(psPh->lstPhrase,psPhs)) {
	
			CHAR * pszStart=NULL;
			CHAR * pszEnd=NULL;
			BOOL bReplace=false;
			#define JUMP_CHARS ",.-()*#/\\~$;:[]{}@=|" // Salto questi carattari prima e dopo il testo per cui è richiesta la traduzione

			if (!psPhs->bTranslate) continue;
			if (strEmpty(psPhs->pszStr)) {psPhs->bTranslate=false; continue;}
			if (strlen(psPhs->pszStr)<2) {psPhs->bTranslate=false; continue;}

			//
			// Estraggo testa della frase
			//
			pszStart=psPhs->pszStr;
			for (p=psPhs->pszStr;*p;p++) {
				if (*p>' '&&!strchr(JUMP_CHARS,*p)) break;
			}
			if (p>psPhs->pszStr) {bReplace=true; psPhs->pszBefore=strTake(psPhs->pszStr,p-1); pszStart=p;}

			//
			// Estraggo coda della frase
			//
			pszEnd=pszStart+strlen(pszStart)-1;
			for (p=pszEnd;p>=pszStart;p--) {
				if (*p>' '&&!strchr(JUMP_CHARS,*p)) break;
			}
			if (p!=pszStart) 
			{
				bReplace=true; 
				psPhs->pszAfter=strTake(p+1,pszEnd); 
				pszEnd=p;
			}
			if (bReplace) {
				p=strTake(pszStart,pszEnd);
				strAssign(&psPhs->pszStr,p);
				ehFreeNN(p);
			
			}
		}

	
	}
	return psPh;
}
Example #6
0
//
// _phraseBreak() > RItorna True se non riesce a spezzare la stringa
//
BOOL _phraseBreak(S_PHRASES * psPh,CHAR * pszPhrase) {

	S_PHSTR sPhs;
	INT iPart;
	INT a,f;
	EH_AR ar;
	INT iLen;
	CHAR * p;
	CHAR szCharBreak[80]="";
	BOOL bTrans=false;

	if (strEmpty(pszPhrase)) return false;

	for (p=pszPhrase;*p;p++) {
		if (*p>' ') {bTrans=true; break;}
	}

	// Solo caratteri di controllo
	if (!bTrans) {
		_(sPhs);
		sPhs.bTranslate=false; 
		sPhs.pszStr=strDup(pszPhrase);
		lstPush(psPh->lstPhrase,&sPhs);
		return false;
	
	}

	if (strlen(pszPhrase)<GOOGLE_MAX_LENGTH)
	{
		_(sPhs);
		sPhs.bTranslate=true; 
		sPhs.pszStr=strDup(pszPhrase);
		lstPush(psPh->lstPhrase,&sPhs);
		psPh->iPhraseToTrans++;
	}
	else
	{
		// Array con 
		CHAR *arDiv[]={".",CRLF,"\r","\n",";"," - ","-",",",NULL};//"(",")",NULL};
		INT x;
		
		iPart=100000;
		for (x=0;arDiv[x];x++)
		{
			f=_tokControl(psPh->psTag->pszSourceTagged,arDiv[x]);
			if (f) 
			{
				if (f>psPh->iMaxPhrases&&psPh->iMaxPhrases) 
					continue;
				if (f<iPart) 
				{
//					pCharBreak=arDiv[x];	
					strcpy(szCharBreak,arDiv[x]);
					iPart=f;
					if (psPh->psTag->bHtml) 
						break;
				}
			}
		}

		//
		// Non riesce a spezzare la stringa > mi fermo
		//
 		if (!*szCharBreak) 
		{
			//_phraseDestroy(psPh);
			psPh->iSeveralError++;
			return true; // = GE_STRING_TOO_LONG
		}
		ar=strSplit(psPh->psTag->pszSourceTagged,szCharBreak);
		iLen=ARLen(ar);
		for (a=0;ar[a];a++) {
		
			_(sPhs);
			sPhs.bTranslate=true; 
			if (iLen<a-1) strcpy(sPhs.szBreak,szCharBreak);
			sPhs.pszStr=strDup(ar[a]);
			lstPush(psPh->lstPhrase,&sPhs);
			psPh->iPhraseToTrans++;
		}
		ehFree(ar);

	}
	return false;
}
Example #7
0
static CHAR *  _azureTokenRequest(ET_PARAM	enParam,CHAR * pszJsonString) {

	EH_WEB *psWeb;
//	CHAR * pszTranslateParams=pszJsonString;
	if (!_s.lstAzureToken) _s.lstAzureToken=lstNew(); // Creo la prima volta la lista

	//
	// Richiedo 'azureToken' a 'mamma' Microsoft
	//
	if (strstr(pszJsonString,"arAzureClient")) {

		CHAR * pszAppTranslatorUrl="https://api.datamarket.azure.com/Bing/MicrosoftTranslator/v1/Translate";
		CHAR * pszScope="http://api.microsofttranslator.com";
		CHAR * pszGrantType="client_credentials";
		CHAR * pszAuthUrl="https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";

		//
		// https://datamarket.azure.com/developer/applications/
		//
		EH_LST lst;
		CHAR * pszUrl;
		S_SEN * psSen;
		INT a,iLen;
		EH_JSON * psJson=jsonCreate(pszJsonString);
//		EH_LST lstToken=lstNew();
		
		lstClean(_s.lstAzureToken);

		if (psJson->enType==JSON_ERROR) ehError();
		iLen=atoi(jsonGet(psJson,"arAzureClient.length"));
		for (a=0;a<iLen;a++) {
	
			CHAR * psz=jsonGetf(psJson,"arAzureClient[%d]",a);
			EH_AR ar;

			if (strEmpty(psz)) continue;
			ar=strSplit(psz,"|");

			psSen=senCreate();
			lst=lstNew();
			lstPushf(lst,"%s?",pszAuthUrl);
			lstPushf(lst,"grant_type=%s",senEncode(psSen,SE_URL,pszGrantType));
			lstPushf(lst,"&scope=%s",pszScope);//senEncode(psSen,SE_URL,pszScope));
			lstPushf(lst,"&client_id=%s",senEncode(psSen,SE_URL,ar[0]));
			lstPushf(lst,"&client_secret=%s",senEncode(psSen,SE_URL,ar[1]));
			senDestroy(psSen);
			pszUrl=lstToString(lst,"","","");
			psWeb=webHttpReq(pszUrl,"POST",NULL,FALSE,60);
			if (enParam&ET_SERVICE_CALL) printf(">azureToken:");
			if (!psWeb->sError.enCode) { // Leggi pagina caricata 
			
				EH_JSON * psJson;
				psJson=jsonCreate(psWeb->pData);
				psz=jsonGet(psJson,"access_token");
				lstPush(_s.lstAzureToken,strEver(psz));
				jsonDestroy(psJson);
				if (enParam&ET_SERVICE_CALL) printf("ok." CRLF);

			} else {
				lstPush(_s.lstAzureToken,"");
				printf("\7Azure Error: Account %s accesso error" CRLF,ar[0]);
				if (enParam&ET_SERVICE_CALL) printf("ko!" CRLF);

			}
			ehFree(ar);
			webHttpReqFree(psWeb);
			ehFree(pszUrl);
			lstDestroy(lst);
		}

		//
		// Aggiungo Token di accesso Trovati
		//
		/*
		if (lstToken->iLength) {
			CHAR * psz=lstToString(lstToken,","," ,arAzureToken:[","]"); xx
			pszTranslateParams[strlen(pszTranslateParams)-1]=0;
			strCat(&pszTranslateParams,psz);
			strCat(&pszTranslateParams,"}");
			ehFree(psz);
		}
		*/

		jsonDestroy(psJson);
//		lstDestroy(lstToken);
	}

//	ehFree(pszJsonString);
	return pszJsonString;
}
Example #8
0
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun(void)
{
    FUNCTION_HARNESS_VOID();

    // *****************************************************************************************************************************
    if (testBegin("strNew(), strNewBuf(), strNewN(), strEmpty(), strPtr(), strSize(), and strFree()"))
    {
        // We don't want this struct to grow since there are generally a lot of strings, so make sure it doesn't grow without us
        // knowing about it
        TEST_RESULT_UINT(sizeof(StringConst), TEST_64BIT() ? 16 : 12, "check StringConst struct size");

        // Test the size macro
        TEST_RESULT_VOID(CHECK_SIZE(555), "valid size");
        TEST_ERROR(CHECK_SIZE(STRING_SIZE_MAX + 1), AssertError, "string size must be <= 1073741824 bytes");

        String *string = strNew("static string");
        TEST_RESULT_STR(strPtr(string), "static string", "new with static string");
        TEST_RESULT_INT(strSize(string), 13, "check size");
        TEST_RESULT_BOOL(strEmpty(string), false, "is not empty");
        TEST_RESULT_INT(strlen(strPtr(string)), 13, "check size with strlen()");
        TEST_RESULT_CHAR(strPtr(string)[2], 'a', "check character");

        TEST_RESULT_VOID(strFree(string), "free string");

        // -------------------------------------------------------------------------------------------------------------------------
        TEST_RESULT_STR(strPtr(strNewN("testmorestring", 4)), "test", "new string with size limit");

        // -------------------------------------------------------------------------------------------------------------------------
        Buffer *buffer = bufNew(8);
        memcpy(bufPtr(buffer), "12345678", 8);
        bufUsedSet(buffer, 8);

        TEST_RESULT_STR(strPtr(strNewBuf(buffer)), "12345678", "new string from buffer");

        // -------------------------------------------------------------------------------------------------------------------------
        string = strNewFmt("formatted %s %04d", "string", 1);
        TEST_RESULT_STR(strPtr(string), "formatted string 0001", "new with formatted string");
        TEST_RESULT_PTR(strPtr(NULL), NULL, "null string pointer");

        TEST_RESULT_VOID(strFree(string), "free string");
        TEST_RESULT_VOID(strFree(NULL), "free null string");
    }

    // *****************************************************************************************************************************
    if (testBegin("STRING_STATIC()"))
    {
        TEST_RESULT_STR(strPtr(TEST_STRING), "a very interesting string!", "check static string");
        TEST_RESULT_STR(strPtr(strSubN(TEST_STRING, 0, 6)), "a very", "read-only strSub() works");
    }

    // *****************************************************************************************************************************
    if (testBegin("strBase() and strPath()"))
    {
        TEST_RESULT_STR(strPtr(strBase(STRDEF(""))), "", "empty string");
        TEST_RESULT_STR(strPtr(strBase(STRDEF("/"))), "", "/ only");
        TEST_RESULT_STR(strPtr(strBase(STRDEF("/file"))), "file", "root file");
        TEST_RESULT_STR(strPtr(strBase(STRDEF("/dir1/dir2/file"))), "file", "subdirectory file");

        TEST_RESULT_STR(strPtr(strPath(STRDEF(""))), "", "empty string");
        TEST_RESULT_STR(strPtr(strPath(STRDEF("/"))), "/", "/ only");
        TEST_RESULT_STR(strPtr(strPath(STRDEF("/file"))), "/", "root path");
        TEST_RESULT_STR(strPtr(strPath(STRDEF("/dir1/dir2/file"))), "/dir1/dir2", "subdirectory file");
    }

    // *****************************************************************************************************************************
    if (testBegin("strCat(), strCatChr(), and strCatFmt()"))
    {
        String *string = strNew("XXXX");
        String *string2 = strNew("ZZZZ");

        TEST_RESULT_STR(strPtr(strCat(string, "YYYY")), "XXXXYYYY", "cat string");
        TEST_RESULT_SIZE(string->extra, 4, "check extra");
        TEST_RESULT_STR(strPtr(strCatFmt(string, "%05d", 777)), "XXXXYYYY00777", "cat formatted string");
        TEST_RESULT_SIZE(string->extra, 6, "check extra");
        TEST_RESULT_STR(strPtr(strCatChr(string, '!')), "XXXXYYYY00777!", "cat chr");
        TEST_RESULT_SIZE(string->extra, 5, "check extra");

        TEST_RESULT_STR(strPtr(string2), "ZZZZ", "check unaltered string");
    }

    // *****************************************************************************************************************************
    if (testBegin("strDup()"))
    {
        const String *string = STRDEF("duplicated string");
        String *stringDup = strDup(string);
        TEST_RESULT_STR(strPtr(stringDup), strPtr(string), "duplicated strings match");

        TEST_RESULT_PTR(strDup(NULL), NULL, "duplicate null string");
    }

    // *****************************************************************************************************************************
    if (testBegin("strBeginsWith() and strBeginsWithZ()"))
    {
        TEST_RESULT_BOOL(strBeginsWith(STRDEF(""), STRDEF("aaa")), false, "empty string");
        TEST_RESULT_BOOL(strBeginsWith(STRDEF("astring"), STRDEF("")), true, "empty begins with");
        TEST_RESULT_BOOL(strBeginsWithZ(STRDEF("astring"), "astr"), true, "partial begins with");
        TEST_RESULT_BOOL(strBeginsWithZ(STRDEF("astring"), "astring"), true, "equal strings");
    }

    // *****************************************************************************************************************************
    if (testBegin("strEndsWith() and strEndsWithZ()"))
    {
        TEST_RESULT_BOOL(strEndsWith(STRDEF(""), STRDEF(".doc")), false, "empty string");
        TEST_RESULT_BOOL(strEndsWith(STRDEF("astring"), STRDEF("")), true, "empty ends with");
        TEST_RESULT_BOOL(strEndsWithZ(STRDEF("astring"), "ing"), true, "partial ends with");
        TEST_RESULT_BOOL(strEndsWithZ(STRDEF("astring"), "astring"), true, "equal strings");
    }

    // *****************************************************************************************************************************
    if (testBegin("strEq(), strEqZ(), strCmp(), strCmpZ()"))
    {
        TEST_RESULT_BOOL(strEq(STRDEF("equalstring"), STRDEF("equalstring")), true, "strings equal");
        TEST_RESULT_BOOL(strEq(STRDEF("astring"), STRDEF("anotherstring")), false, "strings not equal");
        TEST_RESULT_BOOL(strEq(STRDEF("astring"), STRDEF("bstring")), false, "equal length strings not equal");

        TEST_RESULT_INT(strCmp(STRDEF("equalstring"), STRDEF("equalstring")), 0, "strings equal");
        TEST_RESULT_INT(strCmp(STRDEF("a"), STRDEF("b")), -1, "a < b");
        TEST_RESULT_INT(strCmp(STRDEF("b"), STRDEF("a")), 1, "b > a");

        TEST_RESULT_BOOL(strEqZ(STRDEF("equalstring"), "equalstring"), true, "strings equal");
        TEST_RESULT_BOOL(strEqZ(STRDEF("astring"), "anotherstring"), false, "strings not equal");
        TEST_RESULT_BOOL(strEqZ(STRDEF("astring"), "bstring"), false, "equal length strings not equal");

        TEST_RESULT_INT(strCmpZ(STRDEF("equalstring"), "equalstring"), 0, "strings equal");
        TEST_RESULT_INT(strCmpZ(STRDEF("a"), "b"), -1, "a < b");
        TEST_RESULT_INT(strCmpZ(STRDEF("b"), "a"), 1, "b > a");
    }

    // *****************************************************************************************************************************
    if (testBegin("strFirstUpper(), strFirstLower(), strUpper(), strLower()"))
    {
        TEST_RESULT_STR(strPtr(strFirstUpper(strNew(""))), "", "empty first upper");
        TEST_RESULT_STR(strPtr(strFirstUpper(strNew("aaa"))), "Aaa", "first upper");
        TEST_RESULT_STR(strPtr(strFirstUpper(strNew("Aaa"))), "Aaa", "first already upper");

        TEST_RESULT_STR(strPtr(strFirstLower(strNew(""))), "", "empty first lower");
        TEST_RESULT_STR(strPtr(strFirstLower(strNew("AAA"))), "aAA", "first lower");
        TEST_RESULT_STR(strPtr(strFirstLower(strNew("aAA"))), "aAA", "first already lower");

        TEST_RESULT_STR(strPtr(strLower(strNew("K123aBc"))), "k123abc", "all lower");
        TEST_RESULT_STR(strPtr(strLower(strNew("k123abc"))), "k123abc", "already lower");
        TEST_RESULT_STR(strPtr(strLower(strNew("C"))), "c", "char lower");
        TEST_RESULT_STR(strPtr(strLower(strNew(""))), "", "empty lower");

        TEST_RESULT_STR(strPtr(strUpper(strNew("K123aBc"))), "K123ABC", "all upper");
        TEST_RESULT_STR(strPtr(strUpper(strNew("K123ABC"))), "K123ABC", "already upper");
        TEST_RESULT_STR(strPtr(strUpper(strNew("c"))), "C", "char upper");
        TEST_RESULT_STR(strPtr(strUpper(strNew(""))), "", "empty upper");
    }

    // *****************************************************************************************************************************
    if (testBegin("strQuote()"))
    {
        TEST_RESULT_STR(strPtr(strQuote(STRDEF("abcd"), STRDEF("'"))), "'abcd'", "quote string");
    }

    // *****************************************************************************************************************************
    if (testBegin("strReplaceChr()"))
    {
        TEST_RESULT_STR(strPtr(strReplaceChr(strNew("ABCD"), 'B', 'R')), "ARCD", "replace chr");
    }

    // *****************************************************************************************************************************
    if (testBegin("strSub() and strSubN()"))
    {
        TEST_RESULT_STR(strPtr(strSub(STRDEF("ABCD"), 2)), "CD", "sub string");
        TEST_RESULT_STR(strPtr(strSubN(STRDEF("ABCD"), 1, 2)), "BC", "sub string with length");
    }

    // *****************************************************************************************************************************
    if (testBegin("strTrim()"))
    {
        TEST_RESULT_STR(strPtr(strTrim(strNew(""))), "", "trim empty");
        TEST_RESULT_STR(strPtr(strTrim(strNew("X"))), "X", "no trim (one char)");
        TEST_RESULT_STR(strPtr(strTrim(strNew("no-trim"))), "no-trim", "no trim (string)");
        TEST_RESULT_STR(strPtr(strTrim(strNew(" \t\r\n"))), "", "all whitespace");
        TEST_RESULT_STR(strPtr(strTrim(strNew(" \tbegin-only"))), "begin-only", "trim begin");
        TEST_RESULT_STR(strPtr(strTrim(strNew("end-only\t "))), "end-only", "trim end");
        TEST_RESULT_STR(strPtr(strTrim(strNew("\n\rboth\r\n"))), "both", "trim both");
        TEST_RESULT_STR(strPtr(strTrim(strNew("begin \r\n\tend"))), "begin \r\n\tend", "ignore whitespace in middle");
    }

    // *****************************************************************************************************************************
    if (testBegin("strChr() and strTrunc()"))
    {
        TEST_RESULT_INT(strChr(STRDEF("abcd"), 'c'), 2, "c found");
        TEST_RESULT_INT(strChr(STRDEF("abcd"), 'C'), -1, "capital C not found");
        TEST_RESULT_INT(strChr(STRDEF("abcd"), 'i'), -1, "i not found");
        TEST_RESULT_INT(strChr(STRDEF(""), 'x'), -1, "empty string - x not found");

        String *val = strNew("abcdef");
        TEST_ERROR(
            strTrunc(val, (int)(strSize(val) + 1)), AssertError,
            "assertion 'idx >= 0 && (size_t)idx <= this->size' failed");
        TEST_ERROR(strTrunc(val, -1), AssertError, "assertion 'idx >= 0 && (size_t)idx <= this->size' failed");

        TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'd'))), "abc", "simple string truncated");
        strCat(val, "\r\n to end");
        TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'n'))), "abc\r\n to e", "complex string truncated");
        TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'a'))), "", "complete string truncated - empty string");

        TEST_RESULT_INT(strSize(val), 0, "0 size");
        TEST_RESULT_STR(strPtr(strTrunc(val, 0)), "", "test coverage of empty string - no error thrown for index 0");
    }

    // *****************************************************************************************************************************
    if (testBegin("strToLog() and strObjToLog()"))
    {
        TEST_RESULT_STR(strPtr(strToLog(STRDEF("test"))), "{\"test\"}", "format string");
        TEST_RESULT_STR(strPtr(strToLog(NULL)), "null", "format null string");

        char buffer[256];
        TEST_RESULT_UINT(strObjToLog(NULL, (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 4, "format null string");
        TEST_RESULT_STR(buffer, "null", "check null string");

        TEST_RESULT_UINT(strObjToLog(STRDEF("teststr"), (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 11, "format string");
        TEST_RESULT_STR(buffer, "{\"teststr\"}", "check string");
    }

    // *****************************************************************************************************************************
    if (testBegin("strSizeFormat()"))
    {
        TEST_RESULT_STR(strPtr(strSizeFormat(0)), "0B", "zero bytes");
        TEST_RESULT_STR(strPtr(strSizeFormat(1023)), "1023B", "1023 bytes");
        TEST_RESULT_STR(strPtr(strSizeFormat(1024)), "1KB", "1 KB");
        TEST_RESULT_STR(strPtr(strSizeFormat(2200)), "2.1KB", "2.1 KB");
        TEST_RESULT_STR(strPtr(strSizeFormat(1048576)), "1MB", "1 MB");
        TEST_RESULT_STR(strPtr(strSizeFormat(20162900)), "19.2MB", "19.2 MB");
        TEST_RESULT_STR(strPtr(strSizeFormat(1073741824)), "1GB", "1 GB");
        TEST_RESULT_STR(strPtr(strSizeFormat(1073741824 + 107374183)), "1.1GB", "1.1 GB");
        TEST_RESULT_STR(strPtr(strSizeFormat(UINT64_MAX)), "17179869183GB", "uint64 max");
    }

    // *****************************************************************************************************************************
    if (testBegin("strLstNew(), strLstAdd*(), strLstGet(), strLstMove(), strLstSize(), and strLstFree()"))
    {
        // Add strings to the list
        // -------------------------------------------------------------------------------------------------------------------------
        StringList *list = NULL;

        MEM_CONTEXT_TEMP_BEGIN()
        {
            list = strLstNew();

            for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
            {
                if (listIdx == 0)
                {
                    TEST_RESULT_PTR(strLstAdd(list, NULL), list, "add null item");
                }
                else
                    TEST_RESULT_PTR(strLstAdd(list, strNewFmt("STR%02d", listIdx)), list, "add item %d", listIdx);
            }

            strLstMove(list, MEM_CONTEXT_OLD());
        }
        MEM_CONTEXT_TEMP_END();

        TEST_RESULT_INT(strLstSize(list), 9, "list size");

        // Read them back and check values
        // -------------------------------------------------------------------------------------------------------------------------
        for (unsigned int listIdx = 0; listIdx < strLstSize(list); listIdx++)
        {
            if (listIdx == 0)
            {
                TEST_RESULT_PTR(strLstGet(list, listIdx), NULL, "check null item");
            }
            else
                TEST_RESULT_STR(strPtr(strLstGet(list, listIdx)), strPtr(strNewFmt("STR%02u", listIdx)), "check item %u", listIdx);
        }

        TEST_RESULT_VOID(strLstFree(list), "free string list");
        TEST_RESULT_VOID(strLstFree(NULL), "free null string list");
    }