/* * This file is part of firk's window manager for x11 (fwm) * Copyright (C) 2016-2021 firk * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include "main.h" #include "base.h" #include "xkrap.h" /* weird and bad code in this file */ static XFontStruct * fs = NULL; static void init_fs(GC gc) { if(!fs) fs=XQueryFont(display,XGContextFromGC(gc)); } extern int text_width(GC gc, char const * str, int count) { int res; init_fs(gc); if(fs) { res = XTextWidth(fs, str, count); return res; } else return count*8; } extern void getwintitle(Window w, char * dest, unsigned int destsize) { XTextProperty tp; char * * list; int n; if(!dest || destsize<1) return; dest[0] = 0; if(!XGetWMName(display, w, &tp)) return; if(tp.nitems) { if(tp.encoding==XA_STRING) { snprintf(dest, destsize, "%s", tp.value); } else { if(Xutf8TextPropertyToTextList(display, &tp, &list, &n)>=Success && n>0 && *list) { snprintf(dest, destsize, "%s", *list); XFreeStringList(list); } } } if(tp.value) XFree(tp.value); } static XChar2b * convert_to_utf8(char const * s, size_t n, size_t * rn) { XChar2b *tmp; size_t pos, outpos; unsigned char c, c2, c3; unsigned int uc; if(n<1) return NULL; if(n>10000) n=10000; // dirty hack; but really we never need to out strings > 10000 bytes tmp = malloc(sizeof(*tmp)*n); if(!tmp) return NULL; #define SP(X) (*(unsigned char*)(s+(X))) for(outpos=pos=0; pos=2 && (c&0xE0)==0xC0 && ((c2=SP(pos+1))&0xC0)==0x80) { uc = ((c&0x1F)<<6) | (c2&0x3F); pos+=2; } else if(n-pos>=3 && (c&0xF0)==0xE0 && ((c2=SP(pos+1))&0xC0)==0x80 && ((c3=SP(pos+2))&0xC0)==0x80) { uc = ((c&0xF)<<12) | ((c2&0x3F)<<6) | (c3&0x3F); pos+=3; } else { uc='?'; pos++; } tmp[outpos].byte1 = (unsigned char)(uc>>8); tmp[outpos].byte2 = (unsigned char)(uc); outpos++; } #undef SP *rn = outpos; return tmp; } extern void draw_string_utf8(Display *dis, Drawable d, GC gc, int x, int y, char const * s, size_t n) { XChar2b *tmp; size_t rn; if(n<1) return; if(n>10000) n=10000; // dirty hack; but really we never need to out strings > 10000 bytes tmp = convert_to_utf8(s, n, &rn); if(!tmp) { XDrawString(dis, d, gc, x, y, s, n); // fallback and don't care about minor problems; we can't fail return; } XDrawString16(dis, d, gc, x, y, tmp, rn); free(tmp); } extern int text_width_utf8(GC gc, char const * str, int count) { int res; XChar2b *tmp; size_t rn; init_fs(gc); if(fs) { tmp = convert_to_utf8(str, count, &rn); if(!tmp) { res = XTextWidth(fs, str, count); } else { res = XTextWidth16(fs, tmp, rn); free(tmp); } return res; } else return count*8; }