Exemple #1
0
// encode message from UTF8
LPSTR __cdecl cpp_encodeU(HANDLE context, LPCSTR msg)
{
	pCNTX ptr = get_context_on_id(context);
	if (!ptr) return NULL;
	cpp_alloc_pdata(ptr); pSIMDATA p = (pSIMDATA)ptr->pdata;
	if (!p->KeyX) { ptr->error = ERROR_NO_KEYX; return NULL; }

	LPSTR szNewMsg = NULL;
	LPSTR szOldMsg = (LPSTR)msg;

	if (ptr->features & FEATURES_UTF8) {
		// utf8 message: encrypt.
		szNewMsg = cpp_encrypt(ptr, szOldMsg);
	}
	else {
		// utf8 message: convert to ansi and encrypt.
		LPWSTR wstring = utf8decode(szOldMsg);
		int wlen = (int)wcslen(wstring) + 1;
		LPSTR astring = (LPSTR)alloca(wlen);
		WideCharToMultiByte(CP_ACP, 0, (LPWSTR)szOldMsg, -1, astring, wlen, 0, 0);
		szNewMsg = cpp_encrypt(ptr, astring);
	}

	return szNewMsg;
}
Exemple #2
0
// decode message from UTF8 if need, return ANSIzUCS2z
LPSTR __cdecl cpp_decode(HANDLE context, LPCSTR szEncMsg)
{
	pCNTX ptr = get_context_on_id(context);
	if (!ptr) return NULL;
	cpp_alloc_pdata(ptr); pSIMDATA p = (pSIMDATA)ptr->pdata;
	if (!p->KeyX) { ptr->error = ERROR_NO_KEYX; return NULL; }

	LPSTR szNewMsg = NULL;
	LPSTR szOldMsg = cpp_decrypt(ptr, szEncMsg);

	if (szOldMsg) {
		if (ptr->features & FEATURES_UTF8) {
			// utf8 message: convert to unicode -> ansii
			LPWSTR wstring = utf8decode(szOldMsg);
			int wlen = (int)wcslen(wstring) + 1;
			szNewMsg = (LPSTR)mir_alloc(wlen*(sizeof(WCHAR)+2));			// [email protected]
			WideCharToMultiByte(CP_ACP, 0, wstring, -1, szNewMsg, wlen, 0, 0);
			memcpy(szNewMsg + strlen(szNewMsg) + 1, wstring, wlen*sizeof(WCHAR));	// [email protected]
		}
		else {
			// ansi message: convert to unicode
			int slen = (int)strlen(szOldMsg) + 1;
			szNewMsg = (LPSTR)mir_alloc(slen*(sizeof(WCHAR)+1));
			memcpy(szNewMsg, szOldMsg, slen);
			WCHAR* wstring = (LPWSTR)alloca(slen*sizeof(WCHAR));
			MultiByteToWideChar(CP_ACP, 0, szOldMsg, -1, wstring, slen*sizeof(WCHAR));
			memcpy(szNewMsg + slen, wstring, slen*sizeof(WCHAR));
		}
	}
	replaceStr(ptr->tmp, szNewMsg);
	return szNewMsg;
}
Exemple #3
0
/*
 * Render paragraph. TODO: fix line break in long text without spaces.
 */
int32_t osd_paragraph(struct osd_t* osd, char *text, uint32_t text_size, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
  uint32_t width;
  char* iso_text = NULL;
  char* str;
  char* tmp;
  char* space;
  int text_y = y;
  int done = 0;

  if ((!text) || (strlen(text) == 0)) {
    return 0;
  }
  
  iso_text = malloc(strlen(text) + 1);
  utf8decode(text, iso_text);  
  str = iso_text;
  
  do {
    width = osd_fontWidth(osd, str, strlen(str));
    
    if (width <= w) {
      /* We can display the whole line */      
      graphics_resource_render_text_ext(osd->img, x, text_y,
                                   GRAPHICS_RESOURCE_WIDTH,
                                   GRAPHICS_RESOURCE_HEIGHT,
                                   GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                   GRAPHICS_RGBA32(0,0,0,0xc0), /* bg */
                                   str, strlen(str), 40);                                 
      done = 1;                             
    } else {
      tmp = malloc(strlen(str) + 1);
      strcpy(tmp, str);
      while (width > w) {
        space = strrchr(tmp, ' ');  
        tmp[space-tmp] = '\0';
        width = osd_fontWidth(osd, tmp, space - tmp);
      }
      
      graphics_resource_render_text_ext(osd->img, x, text_y,
                                       GRAPHICS_RESOURCE_WIDTH,
                                       GRAPHICS_RESOURCE_HEIGHT,
                                       GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                       GRAPHICS_RGBA32(0,0,0,0xc0), /* bg */
                                       tmp, strlen(tmp), 40);                                       
      text_y += 50;  
      if (text_y > (y + h)) {
        done = 1;
      }  
      str += strlen(tmp) + 1;
      free(tmp);
    }
  } while(!done);
  
  free(iso_text);  
  return 0;
}
Exemple #4
0
size_t
utf8chsiz(char *c, size_t clen)
{
	if(clen <= 0) {
		return 0;
	}
	long cp;
	size_t chsiz = utf8decode(c, &cp, MIN(UTF_SIZ, clen));
	return cp != UTF_INVALID ? chsiz : 1;
}
Exemple #5
0
/*
 * UTF8 decode and render text
 */
void osd_text(struct osd_t* osd, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t fg_color, uint32_t bg_color, char *str)
{
  char* iso_text = NULL;
        
  if (str == NULL) {
    return;
  }
  
  iso_text = malloc(strlen(str) + 1);
  utf8decode(str, iso_text);        
  graphics_resource_render_text_ext(osd->img, x, y, w, h, fg_color, bg_color, iso_text, strlen(iso_text), 40);
  free(iso_text);
}     
Exemple #6
0
int
get_text_width(const font_t* font, const char* text)
{
	uint8_t  ch_byte;
	uint32_t cp;
	uint32_t utf8state;
	int      width = 0;
	
	for (;;) {
		utf8state = UTF8_ACCEPT;
		while (utf8decode(&utf8state, &cp, ch_byte = *text++) > UTF8_REJECT);
		if (utf8state == UTF8_REJECT && ch_byte == '\0')
			--text;  // don't eat NUL terminator
		cp = cp == 0x20AC ? 128
			: cp == 0x201A ? 130
			: cp == 0x0192 ? 131
			: cp == 0x201E ? 132
			: cp == 0x2026 ? 133
			: cp == 0x2020 ? 134
			: cp == 0x2021 ? 135
			: cp == 0x02C6 ? 136
			: cp == 0x2030 ? 137
			: cp == 0x0160 ? 138
			: cp == 0x2039 ? 139
			: cp == 0x0152 ? 140
			: cp == 0x017D ? 142
			: cp == 0x2018 ? 145
			: cp == 0x2019 ? 146
			: cp == 0x201C ? 147
			: cp == 0x201D ? 148
			: cp == 0x2022 ? 149
			: cp == 0x2013 ? 150
			: cp == 0x2014 ? 151
			: cp == 0x02DC ? 152
			: cp == 0x2122 ? 153
			: cp == 0x0161 ? 154
			: cp == 0x203A ? 155
			: cp == 0x0153 ? 156
			: cp == 0x017E ? 158
			: cp == 0x0178 ? 159
			: cp;
		cp = utf8state == UTF8_ACCEPT
			? cp < (uint32_t)font->num_glyphs ? cp : 0x1A
			: 0x1A;
		if (cp == '\0') break;
		width += font->glyphs[cp].width;
	}
	return width;
}
Exemple #7
0
static const char* utf8back(const char* p, const char* start, const char* end)
{
  const char* a;
  int len;
  // if we are not pointing at a continuation character, we are done:
  if ((*p&0xc0) != 0x80) return p;
  // search backwards for a 0xc0 starting the character:
  for (a = p-1; ; --a) {
    if (a < start) return p;
    if (!(a[0]&0x80)) return p;
    if ((a[0]&0x40)) break;
  }
  utf8decode(a,end,&len);
  if (a+len > p) return a;
  return p;
}
Exemple #8
0
void osd_show_info(struct osd_t* osd, int channel_id, int timeout)
{
  char str[128];
  int server;
  
  channels_geteventid(channel_id,&osd->event,&server);
  channels_getnexteventid(channel_id,&osd->nextEvent,&server);

  struct event_t* event = event_copy(osd->event,server);
  struct event_t* nextEvent = event_copy(osd->nextEvent,server);

  fprintf(stderr,"***OSD: event=%d\n",(event ? event->eventId : -1));
  event_dump(event);
  fprintf(stderr,"***OSD: nextEvent=%d\n",(nextEvent ? nextEvent->eventId : -1));
  event_dump(nextEvent);
  fprintf(stderr,"******\n");
  snprintf(str,sizeof(str),"%03d - %s",channels_getlcn(channel_id),channels_getname(channel_id));
  char* iso_text = malloc(strlen(str)+1);
  utf8decode(str,iso_text);

  pthread_mutex_lock(&osd->osd_mutex);
  
  osd_show_channelname(osd,iso_text);

  osd_show_time(osd);

  osd_show_eventinfo(osd,event,nextEvent);

  graphics_update_displayed_resource(osd->img, 0, 0, 0, 0);
  pthread_mutex_unlock(&osd->osd_mutex);

  free(iso_text);

  osd->osd_state = OSD_INFO;
  if (timeout) {
    osd->osd_cleartime = get_time() + timeout;
  }

  event_free(event);
  event_free(nextEvent);
}
int main(int argc, char* argv[])
{
    iconv_t sConv;
    const char* pszSrcEncoding;
    const char* pszDstEncoding = "UTF-8";
    int i;
    int nLastIdentical = -1;

    if( argc != 2 )
    {
        fprintf(stderr, "Usage: generate_encoding_table encoding_name\n");
        return 1;
    }

    pszSrcEncoding = argv[1];

    sConv = iconv_open( pszDstEncoding, pszSrcEncoding );

    if ( sConv == (iconv_t)-1 )
    {
        fprintf(stderr, 
                  "Recode from %s to %s failed with the error: \"%s\".", 
                  pszSrcEncoding, pszDstEncoding, strerror(errno) );
        return 1;
    }

    for(i = 0; i < 256; i++)
    {
        char szSrcBuf[2] = {(char)i, 0};
        char szDstBuf[5] = {0,0,0,0,0};
        char *pszSrcBuf = szSrcBuf;
        char *pszDstBuf = szDstBuf;
        size_t  nSrcLen = strlen( szSrcBuf );
        size_t  nDstLen = sizeof(szDstBuf);
        size_t  nConverted =
            iconv( sConv, &pszSrcBuf, &nSrcLen, &pszDstBuf, &nDstLen );

        int nUnicode = -1;
        if( nConverted == -1 )
        {
            if ( errno == EILSEQ )
            {
                /* fprintf(stderr, "EILSEQ for %d\n", i); */
            }

            else if ( errno == E2BIG )
            {
                fprintf(stderr, "E2BIG for %d\n", i);
                return 1;
            }
            else
            {
                fprintf(stderr, "other error for %d\n", i);
                return 1;
            }
        }
        else
        {
            int len;
            nUnicode = utf8decode(szDstBuf, szDstBuf + strlen(szDstBuf), &len);
            if( nUnicode == 0xfffd )
                nUnicode = -1;
        }

        if( nLastIdentical >= 0 && i != nUnicode )
        {
            if( nLastIdentical + 1 == i )
                printf("info->map[0x%02X] = 0x%02X;\n", nLastIdentical, nLastIdentical);
            else
            {
                printf("for(i = 0x%02X; i < 0x%02X; i++)\n", nLastIdentical, i);
                printf("    info->map[i] = i;\n");
            }
            nLastIdentical = -1;
        }

        if( nUnicode < 0 )
            printf("info->map[0x%02X] = -1;\n", i);
        else if (nUnicode <= 0xFF )
        {
            if( i == nUnicode )
            {
                if( nLastIdentical < 0 )
                    nLastIdentical = i;
            }
            else
                printf("info->map[0x%02X] = 0x%02X;\n", i, nUnicode);
        }
        else if (nUnicode <= 0xFFFF )
            printf("info->map[0x%02X] = 0x%04X;\n", i, nUnicode);
        else if (nUnicode <= 0xFFFFFF )
            printf("info->map[0x%02X] = 0x%06X;\n", i, nUnicode);
        else
            printf("info->map[0x%02X] = 0x%08X;\n", i, nUnicode);
    }

    if( nLastIdentical >= 0 )
    {
        if( nLastIdentical + 1 == i )
            printf("info->map[0x%02X] = 0x%02X;\n", nLastIdentical, nLastIdentical);
        else
        {
            printf("for(i = 0x%02X; i < 0x%02X; i++)\n", nLastIdentical, i);
            printf("    info->map[i] = i;\n");
        }
        nLastIdentical = -1;
    }

    iconv_close( sConv );

    return 0;
}
Exemple #10
0
/*
*	Convert the src string to UTF8 coding dst string, and cut to length
*/
int string2utf8(unsigned char *src, unsigned char* dst, unsigned int length)
{
	unsigned char *pt;
	unsigned char ch;
	unsigned short ucode;
	unsigned int type;
	unsigned int len;

	len = 0;
	type = 0;
	pt = src;
	while(*pt)
	{
		pt = utf8decode(pt, &ucode);
		if(ucode < 0x4e00) {
			if(ucode == 0 || ucode > 0x7F) {
				type = 1;
				break;
			}
		} else if(ucode > 0x9FCF) {
			type = 1;
			break;
		}
		else
			len++;

		if(len >= 3) break;	//There is enough UTF8, so it is, to save time(>_*)
	}

	if(type == 0)	//UTF8
	{
		while(*src)
		{
			ch = *src++;
			*dst++ = ch;

			if(ch < 0x80) {
				if(length > 1) length -= 1;
				else break;
			} else if (ch < 0xe0) { /* U-00000080 - U-000007FF, 2 bytes */
				if(length > 2) length -= 2;
				else break;
				*dst++ = *src++;
			} else if (ch < 0xf0) { /* U-00000800 - U-0000FFFF, 3 bytes */
				if(length > 3) length -= 3;
				else break;
				*dst++ = *src++;
				*dst++ = *src++;
			} else if (ch < 0xf5) { /* U-00010000 - U-001FFFFF, 4 bytes */
				if(length > 4) length -= 4;
				else break;
				*dst++ = *src++;
				*dst++ = *src++;
				*dst++ = *src++;
			} else {
				break;
			}
		}
		*dst = '\0';
	}
	else //assume it is GBK code
	{
		//GBK to UTF8
		while(*src)
		{
			ch = *src;
			if(ch < 0x80)
			{
				if(length > 1) length -= 1;
				else break;

				*dst++= ch;
				src ++;
			}
			else
			{
				ucode = charsets_gbk_to_ucs(src);

				if (ucode < 0x800) //2 bytes
				{
					if(length > 2) length -= 2;
					else break;
	
					*dst++ = 0xC0 | ((ucode >> 6) & 0x1F);
					*dst++ = 0x80 | (ucode & 0x3F);
				}
				else //3 bytes
				{
					if(length > 3) length -= 3;
					else break;

					*dst++ = 0xE0 | (ucode >> 12);
					*dst++ = 0x80 | ((ucode >>6) & 0x3F);
					*dst++ = 0x80 | (ucode & 0x3F);
				}

				src += 2;
			}
		}
		*dst = '\0';
	}
Exemple #11
0
static void osd_show_eventinfo(struct osd_t* osd, struct event_t* event, struct event_t* nextEvent)
{
  char str[64];
  struct tm start_time;
  struct tm stop_time;
  int duration;
  int width = 1920-2*OSD_XMARGIN;
  int height = 380-OSD_YMARGIN;

  osd_draw_window(osd,OSD_XMARGIN,700,width,height);

  if (event==NULL)
    return;

  /* Start/stop time - current event */
  localtime_r((time_t*)&event->start,&start_time);
  localtime_r((time_t*)&event->stop,&stop_time);
  duration = event->stop - event->start;

  snprintf(str,sizeof(str),"%02d:%02d - %02d:%02d",start_time.tm_hour,start_time.tm_min,stop_time.tm_hour,stop_time.tm_min);
  graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+50, 720,
                                     width,
                                     height,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     str, strlen(str), 40);

  /* Title - current event */
  if (event->title) {
    char* iso_text = malloc(strlen(event->title)+1);
    utf8decode(event->title,iso_text);
    graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+350, 720,
                                       width,
                                       height,
                                       GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                       GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                       iso_text, strlen(iso_text), 40);
    free(iso_text);
  }

  snprintf(str,sizeof(str),"%dh %02dm",duration/3600,(duration%3600)/60);
  graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+50, 800,
                                     width,
                                     height,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     str, strlen(str), 30);

  if ((event->episodeNumber) || (event->seasonNumber)) {
    if (!event->episodeNumber) {
      snprintf(str,sizeof(str),"Season %d",event->seasonNumber);
    } else if (!event->seasonNumber) {
      snprintf(str,sizeof(str),"Episode %d",event->episodeNumber);
    } else {
      snprintf(str,sizeof(str),"Season %d, Ep. %d",event->seasonNumber,event->episodeNumber);
    }
    graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+50, 838,
                                     width,
                                     height,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     str, strlen(str), 30);
  }

  if (event->description) {
    char* iso_text = malloc(strlen(event->description)+1);
    utf8decode(event->description,iso_text);
    render_paragraph(osd->img,iso_text,30,OSD_XMARGIN+350,800);
    free(iso_text);
  }


  if (nextEvent) {
    osd_draw_window(osd,OSD_XMARGIN,1002,width,78-OSD_YMARGIN);
    /* Start/stop time - next event */
    localtime_r((time_t*)&nextEvent->start,&start_time);
    localtime_r((time_t*)&nextEvent->stop,&stop_time);

    snprintf(str,sizeof(str),"%02d:%02d - %02d:%02d",start_time.tm_hour,start_time.tm_min,stop_time.tm_hour,stop_time.tm_min);
    graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+50, 1020,
                                       width,
                                       height,
                                       GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                       GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                       str, strlen(str), 40);


    if (nextEvent->title) {
      char* iso_text = malloc(strlen(nextEvent->title)+1);
      utf8decode(nextEvent->title,iso_text);
      graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+350, 1020,
                                         width,
                                         height,
                                         GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                         GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                         iso_text, strlen(iso_text), 40);
      free(iso_text);
    }
  }


  //fprintf(stderr,"Title:       %s\n",event->title);
  //fprintf(stderr,"Start:       %04d-%02d-%02d %02d:%02d:%02d\n",start_time.tm_year+1900,start_time.tm_mon+1,start_time.tm_mday,start_time.tm_hour,start_time.tm_min,start_time.tm_sec);
  //fprintf(stderr,"Stop:        %04d-%02d-%02d %02d:%02d:%02d\n",stop_time.tm_year+1900,stop_time.tm_mon+1,stop_time.tm_mday,stop_time.tm_hour,stop_time.tm_min,stop_time.tm_sec);
  //fprintf(stderr,"Duration:    %02d:%02d:%02d\n",
  //fprintf(stderr,"Description: %s\n",event->description);
}
Exemple #12
0
int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text)
{
	char buf[1024];
	int tx, ty, th;
	Extnts tex;
	XftDraw *d = NULL;
	Fnt *curfont, *nextfont;
	size_t i, len;
	int utf8strlen, utf8charlen, render;
	long utf8codepoint = 0;
	const char *utf8str;
	FcCharSet *fccharset;
	FcPattern *fcpattern;
	FcPattern *match;
	XftResult result;
	int charexists = 0;

	if (!drw->scheme || !drw->fontcount)
		return 0;

	if (!(render = x || y || w || h)) {
		w = ~w;
	} else {
		XSetForeground(drw->dpy, drw->gc, drw->scheme->bg->pix);
		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
		d = XftDrawCreate(drw->dpy, drw->drawable,
		                  DefaultVisual(drw->dpy, drw->screen),
		                  DefaultColormap(drw->dpy, drw->screen));
	}

	curfont = drw->fonts[0];
	while (1) {
		utf8strlen = 0;
		utf8str = text;
		nextfont = NULL;
		while (*text) {
			utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
			for (i = 0; i < drw->fontcount; i++) {
				charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint);
				if (charexists) {
					if (drw->fonts[i] == curfont) {
						utf8strlen += utf8charlen;
						text += utf8charlen;
					} else {
						nextfont = drw->fonts[i];
					}
					break;
				}
			}

			if (!charexists || (nextfont && nextfont != curfont))
				break;
			else
				charexists = 0;
		}

		if (utf8strlen) {
			drw_font_getexts(curfont, utf8str, utf8strlen, &tex);
			/* shorten text if necessary */
			for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--)
				drw_font_getexts(curfont, utf8str, len, &tex);

			if (len) {
				memcpy(buf, utf8str, len);
				buf[len] = '\0';
				if (len < utf8strlen)
					for (i = len; i && i > len - 3; buf[--i] = '.');

				if (render) {
					th = curfont->ascent + curfont->descent;
					ty = y + (h / 2) - (th / 2) + curfont->ascent;
					tx = x + (h / 2);
					XftDrawStringUtf8(d, &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len);
				}
				x += tex.w;
				w -= tex.w;
			}
		}

		if (!*text) {
			break;
		} else if (nextfont) {
			charexists = 0;
			curfont = nextfont;
		} else {
			/* Regardless of whether or not a fallback font is found, the
			 * character must be drawn.
			 */
			charexists = 1;

			if (drw->fontcount >= DRW_FONT_CACHE_SIZE)
				continue;

			fccharset = FcCharSetCreate();
			FcCharSetAddChar(fccharset, utf8codepoint);

			if (!drw->fonts[0]->pattern) {
				/* Refer to the comment in drw_font_xcreate for more
				 * information. */
				die("the first font in the cache must be loaded from a font string.\n");
			}

			fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern);
			FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
			FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);

			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
			FcDefaultSubstitute(fcpattern);
			match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);

			FcCharSetDestroy(fccharset);
			FcPatternDestroy(fcpattern);

			if (match) {
				curfont = drw_font_xcreate(drw, NULL, match);
				if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) {
					drw->fonts[drw->fontcount++] = curfont;
				} else {
					drw_font_free(curfont);
					curfont = drw->fonts[0];
				}
			}
		}
	}
	if (d)
		XftDrawDestroy(d);

	return x;
}
Exemple #13
0
wraptext_t*
word_wrap_text(const font_t* font, const char* text, int width)
{
	char*       buffer = NULL;
	uint8_t     ch_byte;
	char*		carry;
	size_t      ch_size;
	uint32_t    cp;
	int         glyph_width;
	bool        is_line_end = false;
	int         line_idx;
	int         line_width;
	int         max_lines = 10;
	char*       last_break;
	char*       last_space;
	char*       last_tab;
	char*       line_buffer;
	size_t      line_length;
	char*       new_buffer;
	size_t      pitch;
	uint32_t    utf8state;
	wraptext_t* wraptext;
	const char  *p, *start;

	if (!(wraptext = calloc(1, sizeof(wraptext_t)))) goto on_error;
	
	// allocate initial buffer
	get_font_metrics(font, &glyph_width, NULL, NULL);
	pitch = 4 * (glyph_width > 0 ? width / glyph_width : width) + 3;
	if (!(buffer = malloc(max_lines * pitch))) goto on_error;
	if (!(carry = malloc(pitch))) goto on_error;

	// run through one character at a time, carrying as necessary
	line_buffer = buffer; line_buffer[0] = '\0';
	line_idx = 0; line_width = 0; line_length = 0;
	memset(line_buffer, 0, pitch);  // fill line with NULs
	p = text;
	do {
		utf8state = UTF8_ACCEPT; start = p;
		while (utf8decode(&utf8state, &cp, ch_byte = *p++) > UTF8_REJECT);
		if (utf8state == UTF8_REJECT && ch_byte == '\0')
			--p;  // don't eat NUL terminator
		ch_size = p - start;
		cp = cp == 0x20AC ? 128
			: cp == 0x201A ? 130
			: cp == 0x0192 ? 131
			: cp == 0x201E ? 132
			: cp == 0x2026 ? 133
			: cp == 0x2020 ? 134
			: cp == 0x2021 ? 135
			: cp == 0x02C6 ? 136
			: cp == 0x2030 ? 137
			: cp == 0x0160 ? 138
			: cp == 0x2039 ? 139
			: cp == 0x0152 ? 140
			: cp == 0x017D ? 142
			: cp == 0x2018 ? 145
			: cp == 0x2019 ? 146
			: cp == 0x201C ? 147
			: cp == 0x201D ? 148
			: cp == 0x2022 ? 149
			: cp == 0x2013 ? 150
			: cp == 0x2014 ? 151
			: cp == 0x02DC ? 152
			: cp == 0x2122 ? 153
			: cp == 0x0161 ? 154
			: cp == 0x203A ? 155
			: cp == 0x0153 ? 156
			: cp == 0x017E ? 158
			: cp == 0x0178 ? 159
			: cp;
		cp = utf8state == UTF8_ACCEPT
			? cp < (uint32_t)font->num_glyphs ? cp : 0x1A
			: 0x1A;
		switch (cp) {
		case '\n': case '\r':  // explicit newline
			if (cp == '\r' && *p == '\n') ++text;  // CRLF
			is_line_end = true;
			break;
		case '\t':  // tab
			line_buffer[line_length++] = cp;
			line_width += get_text_width(font, "   ");
			is_line_end = false;
			break;
		case '\0':  // NUL terminator
			is_line_end = line_length > 0;  // commit last line on EOT
			break;
		default:  // default case, copy character as-is
			memcpy(line_buffer + line_length, start, ch_size);
			line_length += ch_size;
			line_width += get_glyph_width(font, cp);
			is_line_end = false;
		}
		if (is_line_end) carry[0] = '\0';
		if (line_width > width || line_length >= pitch - 1) {
			// wrap width exceeded, carry current word to next line
			is_line_end = true;
			last_space = strrchr(line_buffer, ' ');
			last_tab = strrchr(line_buffer, '\t');
			last_break = last_space > last_tab ? last_space : last_tab;
			if (last_break != NULL)  // word break (space or tab) found
				strcpy(carry, last_break + 1);
			else  // no word break, so just carry last character
				sprintf(carry, "%c", line_buffer[line_length - 1]);
			line_buffer[line_length - strlen(carry)] = '\0';
		}
		if (is_line_end) {
			// do we need to enlarge the buffer?
			if (++line_idx >= max_lines) {
				max_lines *= 2;
				if (!(new_buffer = realloc(buffer, max_lines * pitch)))
					goto on_error;
				buffer = new_buffer;
				line_buffer = buffer + line_idx * pitch;
			}
			else
				line_buffer += pitch;
			
			memset(line_buffer, 0, pitch);  // fill line with NULs

			// copy carry text into new line
			line_width = get_text_width(font, carry);
			line_length = strlen(carry);
			strcpy(line_buffer, carry);
		}
	} while (cp != '\0');
	free(carry);
	wraptext->num_lines = line_idx;
	wraptext->buffer = buffer;
	wraptext->pitch = pitch;
	return wraptext;

on_error:
	free(buffer);
	free(wraptext);
	return NULL;
}
Exemple #14
0
void
draw_text(const font_t* font, color_t color, int x, int y, text_align_t alignment, const char* text)
{
	uint8_t  ch_byte;
	uint32_t cp;
	int      tab_width;
	uint32_t utf8state;
	
	if (alignment == TEXT_ALIGN_CENTER)
		x -= get_text_width(font, text) / 2;
	else if (alignment == TEXT_ALIGN_RIGHT)
		x -= get_text_width(font, text);
	
	tab_width = font->glyphs[' '].width * 3;
	al_hold_bitmap_drawing(true);
	for (;;) {
		utf8state = UTF8_ACCEPT;
		while (utf8decode(&utf8state, &cp, ch_byte = *text++) > UTF8_REJECT);
		if (utf8state == UTF8_REJECT && ch_byte == '\0')
			--text;  // don't eat NUL terminator
		cp = cp == 0x20AC ? 128
			: cp == 0x201A ? 130
			: cp == 0x0192 ? 131
			: cp == 0x201E ? 132
			: cp == 0x2026 ? 133
			: cp == 0x2020 ? 134
			: cp == 0x2021 ? 135
			: cp == 0x02C6 ? 136
			: cp == 0x2030 ? 137
			: cp == 0x0160 ? 138
			: cp == 0x2039 ? 139
			: cp == 0x0152 ? 140
			: cp == 0x017D ? 142
			: cp == 0x2018 ? 145
			: cp == 0x2019 ? 146
			: cp == 0x201C ? 147
			: cp == 0x201D ? 148
			: cp == 0x2022 ? 149
			: cp == 0x2013 ? 150
			: cp == 0x2014 ? 151
			: cp == 0x02DC ? 152
			: cp == 0x2122 ? 153
			: cp == 0x0161 ? 154
			: cp == 0x203A ? 155
			: cp == 0x0153 ? 156
			: cp == 0x017E ? 158
			: cp == 0x0178 ? 159
			: cp;
		cp = utf8state == UTF8_ACCEPT
			? cp < (uint32_t)font->num_glyphs ? cp : 0x1A
			: 0x1A;
		if (cp == '\0')
			break;
		else if (cp == '\t')
			x += tab_width;
		else {
			draw_image_masked(font->glyphs[cp].image, color, x, y);
			x += font->glyphs[cp].width;
		}
	}
	al_hold_bitmap_drawing(false);
}