#include <stdlib.h>              
#include <iostream>
#include<unistd.h>
#include <sstream>
#include <string>              
#include <X11/Xlib.h>            
#include <X11/Xutil.h>          
#include <X11/Xft/Xft.h> 
#include <X11/extensions/XShm.h>      
#include <sys/ipc.h> 
#include <sys/shm.h>
using namespace std;  
int main()
{
	Display *display = XOpenDisplay(NULL);
	Screen *scn = DefaultScreenOfDisplay(display);
	int screen_num = DefaultScreen(display);
	int screen_width = DisplayWidth(display, screen_num);
	int screen_height = DisplayHeight(display, screen_num);
	int defaultScnDepth = DefaultDepthOfScreen(scn);
	Visual *visual = DefaultVisualOfScreen(scn);
	Window window=XCreateSimpleWindow(display,RootWindow(display,screen_num), 50, 50, 400, 400, 2 ,BlackPixel(display,screen_num),WhitePixel(display,screen_num));
	//XFlush(display)
	XMapWindow(display, window);
	XShmSegmentInfo shmInfo;
	XImage *xImage;
	Pixmap backPixmap;
	(xImage) = XShmCreateImage(display, visual, defaultScnDepth, ZPixmap, NULL, &shmInfo, screen_width, screen_height);
	shmInfo.shmid = shmget(IPC_PRIVATE, (xImage)->bytes_per_line * (xImage)->height, IPC_CREAT | 0777);
	shmInfo.shmaddr = (char *) shmat(shmInfo.shmid, 0, 0);
	xImage->data = shmInfo.shmaddr;
	shmInfo.readOnly = False;
	XShmAttach(display, &shmInfo);
	(backPixmap) = XShmCreatePixmap(display, window, (char *) (shmInfo.shmaddr), &shmInfo, (xImage)->width, (xImage)->height, (xImage)->depth);
	XGCValues values;
	GC gc = XCreateGC(display, backPixmap, 0, &values);
	XSync(display, false);
	
	Drawable drawable =backPixmap;
	visual = DefaultVisual(display, DefaultScreen(display));
	Colormap colormap = XCreateColormap(display, window, visual, AllocNone);
	//gc = XCreateGC(display, drawable, 0, &values);
	//XFlushGC(display, gc);
	const char *text = "Hello";
	XftDraw *xftDraw = NULL;
	XRenderColor xrFGColor, xrBGColor;
	XftColor     xftFGColor, xftBGColor;
	XftFont *font = NULL;
	font = XftFontOpenName( display, DefaultScreen( display ), "morpheus-18" );  
	xftDraw = XftDrawCreate(display, drawable, visual, colormap);
	int nextLineStartY, rectYRef;
	bool firstIte;
	unsigned int rectX, rectY, rectWidth, rectHeight;

	nextLineStartY = 0; rectYRef = 0;
	firstIte = true;
	rectX = 0; rectY = 0; rectWidth = 0; rectHeight = 0;

	std::istringstream strStream(text);
	std::string line;

	while(std::getline(strStream, line))

	{
		
		const char *lineText = line.c_str();
		if(*lineText == '\0')
		{
			nextLineStartY += rectHeight + 1;
			continue;
		}

		const char *text = lineText;
		XGlyphInfo extents;
		XftTextExtents8(display, font, (XftChar8 *)text, strlen(text), &extents);
		unsigned int width = extents.width;
		unsigned int height = extents.height;
		int ascent = extents.y;
		int lBearing = extents.x;
		rectX = 50 - lBearing - 1;
		rectY = 50 - ascent - 1;
		rectWidth = width + 2 * 1;
		rectHeight = height + 5 + 1;
		if(firstIte)
		{
			rectYRef = rectY;
			firstIte = false;
		}
		int diff = rectYRef - rectY;
		rectY += nextLineStartY + diff;
		nextLineStartY += rectHeight + 1;
		if(1)
		{
			xrBGColor.red = 0x7fff;
			xrBGColor.green= 0x7fff;
			xrBGColor.blue = 0x7fff;
			xrBGColor.alpha= 0xffff;
			XftColorAllocValue(display, visual, colormap, &xrBGColor, &xftBGColor);
			//  Draw background fill rectangle
			XftDrawRect(xftDraw, &xftBGColor, rectX, rectY, rectWidth, rectHeight);
			XftColorFree(display, visual, colormap, &xftBGColor);
		}
		xrFGColor.red =  0xbfff;
		xrFGColor.green =  0xbfff;
		xrFGColor.blue =  0xbfff;
		xrFGColor.alpha= 0xffff;
		XftColorAllocValue(display, visual, colormap, &xrFGColor, &xftFGColor);
		//	Overlay Text
		XftDrawString8(xftDraw, &xftFGColor, font, 50, 50, (XftChar8 *) text, strlen(text));

		XColor xForeColor;
		xForeColor.red = 0xafff;
		xForeColor.green = 0xafff;
		xForeColor.blue = 0xffff;
		if(XAllocColor(display,colormap,&xForeColor))
			XSetForeground(display,gc,xForeColor.pixel);
		XftColorFree(display, visual, colormap, &xftFGColor);
		XFreeColors(display, colormap, &(xForeColor.pixel), 1, 0);
	}

	XftDrawDestroy(xftDraw);
	XShmPutImage(display, window, gc, xImage, 0, 0, 0, 0, 400, 400, false);
	XSync(display, false);
	getchar();

}
