changeset 3471:7fb93ecd631c

[gaim-migrate @ 3522] whoops. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Thu, 29 Aug 2002 21:12:00 +0000
parents 2f8f4f1dac98
children d33ec392a5e1
files src/gtkimhtml.c
diffstat 1 files changed, 242 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- a/src/gtkimhtml.c	Thu Aug 29 18:18:41 2002 +0000
+++ b/src/gtkimhtml.c	Thu Aug 29 21:12:00 2002 +0000
@@ -279,7 +279,7 @@
 	GdkPixmap *pm;
 	GdkBitmap *bm;
 
-	PangoLayout *layout;
+	GdkFont *font;
 	GdkColor *fore;
 	GdkColor *back;
 	GdkColor *bg;
@@ -500,6 +500,16 @@
 		return;
 	}
 
+	if (bit->back != NULL) {
+		gdk_color_alloc (cmap, bit->back);
+		gdk_gc_set_foreground (gc, bit->back);
+		gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff,
+				    gdk_string_width (bit->font, line->text), line->height);
+		bg = bit->back;
+	}
+
+	bg = gdk_color_copy (bg);
+
 	if (line->selected) {
 		gint width, x;
 		
@@ -514,12 +524,12 @@
 		if (start == NULL)
 			x = 0;
 		else
-			x = 100; //gdk_text_width (bit->font, line->text, start - line->text);
+			x = gdk_text_width (bit->font, line->text, start - line->text);
 
 		if (end == NULL)
 			end = strchr(line->text, '\0');
 		
-		width = 100; //gdk_text_width (bit->font, line->text, end - line->text) - x;
+		width = gdk_text_width (bit->font, line->text, end - line->text) - x;
 
 		gdk_gc_set_foreground (gc, imhtml->default_hl_color);
 		
@@ -549,54 +559,53 @@
 		gdk_gc_set_foreground (gc, fg);
 	}
 
-	//if (start) {
-	//int offset = 0;
-	//	gdk_draw_layout (window, *gc, line->x - xoff,
-	//		 line->y - yoff + line->ascent, line->text,
-	//			 bit->layout);
-		//	offset = gdk_text_width(bit->font, line->text, start - line->text);
-	//	if (bit->underline || bit->url)
-	//		gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, 
-	//				    line->y - yoff + line->ascent + 1,
-	//				    offset, 1);
-		//if (bit->strike)
-		//	gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
-		//			    line->y - yoff + line->ascent - (bit->font->ascent / 2),
-		//			    offset, 1);
-	//	gdk_gc_set_foreground (gc, imhtml->default_hlfg_color);
-		//gdk_draw_layout (window, bit->font, gc, line->x - xoff + offset,
-		//	       line->y - yoff + line->ascent, start, end - start);
-		//if (bit->underline || bit->url)
-			//gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, 
-			//		    line->y - yoff + line->ascent + 1,
-			//		    gdk_text_width(bit->font, line->text, end - start), 1);
-		//	if (bit->strike)
-			//gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset,
-			//		    line->y - yoff + line->ascent - (bit->font->ascent / 2),
-			//		    gdk_text_width(bit->font, line->text, end - start), 1);
-			//offset = gdk_text_width(bit->font, line->text, end - line->text);
-					     //	gdk_gc_set_foreground (gc, fg);
-		//gdk_draw_string (window, bit->font, gc, line->x - xoff + offset,
-		//	       line->y - yoff + line->ascent, end);
-		//if (bit->underline || bit->url)
-			//gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, 
-			//		    line->y - yoff + line->ascent + 1,
-			//		    gdk_string_width(bit->font, end), 1);
-		//if (bit->strike)
-		//	gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset,
-		//			    line->y - yoff + line->ascent - (bit->font->ascent / 2),
-		//			    gdk_string_width(bit->font, end), 1);
-	//} else {
-		gdk_draw_layout (window, gc, line->x - xoff,
-				 line->y - yoff + line->ascent, bit->layout);
+	if (start) {
+		int offset = 0;
+		gdk_draw_text (window, bit->font, gc, line->x - xoff,
+			       line->y - yoff + line->ascent, line->text, start - line->text);
+		offset = gdk_text_width(bit->font, line->text, start - line->text);
+		if (bit->underline || bit->url)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, 
+					    line->y - yoff + line->ascent + 1,
+					    offset, 1);
+		if (bit->strike)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
+					    line->y - yoff + line->ascent - (bit->font->ascent / 2),
+					    offset, 1);
+		gdk_gc_set_foreground (gc, imhtml->default_hlfg_color);
+		gdk_draw_text (window, bit->font, gc, line->x - xoff + offset,
+			       line->y - yoff + line->ascent, start, end - start);
+		if (bit->underline || bit->url)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, 
+					    line->y - yoff + line->ascent + 1,
+					    gdk_text_width(bit->font, line->text, end - start), 1);
+		if (bit->strike)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset,
+					    line->y - yoff + line->ascent - (bit->font->ascent / 2),
+					    gdk_text_width(bit->font, line->text, end - start), 1);
+		offset = gdk_text_width(bit->font, line->text, end - line->text);
+		gdk_gc_set_foreground (gc, fg);
+		gdk_draw_string (window, bit->font, gc, line->x - xoff + offset,
+			       line->y - yoff + line->ascent, end);
+		if (bit->underline || bit->url)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, 
+					    line->y - yoff + line->ascent + 1,
+					    gdk_string_width(bit->font, end), 1);
+		if (bit->strike)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset,
+					    line->y - yoff + line->ascent - (bit->font->ascent / 2),
+					    gdk_string_width(bit->font, end), 1);
+	} else {
+		gdk_draw_string (window, bit->font, gc, line->x - xoff,
+				 line->y - yoff + line->ascent, line->text);
 		
-		//if (bit->underline || bit->url)
-		//	gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff + line->ascent + 1,
-		//			    gdk_string_width (bit->font, line->text), 1);
-		//if (bit->strike)
-		//	gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
-		//			    line->y - yoff + line->ascent - (bit->font->ascent / 2),
-		//			    gdk_string_width (bit->font, line->text), 1);
+		if (bit->underline || bit->url)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff + line->ascent + 1,
+					    gdk_string_width (bit->font, line->text), 1);
+		if (bit->strike)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
+					    line->y - yoff + line->ascent - (bit->font->ascent / 2),
+					    gdk_string_width (bit->font, line->text), 1);
 	}
 		
 	gdk_color_free (bg);
@@ -1092,7 +1101,7 @@
 		return text;
 
 	for (pos = text; *pos != '\0'; pos++) {
-		gint char_width = 7;//gdk_text_width (chunk->bit->font, pos, 1);
+		gint char_width = gdk_text_width (chunk->bit->font, pos, 1);
 		if ((width > total) && (width <= total + char_width)) {
 			if (width < total + (char_width / 2))
 				return pos;
@@ -2056,41 +2065,168 @@
 	return gdk_x11_font_get_name(font);
 }
 
-static PangoLayout*
-gtk_imhtml_font_load (const char *text,
-		      GtkIMHtml *imhtml,
+static GdkFont*
+gtk_imhtml_font_load (GtkIMHtml *imhtml,
 		      gchar     *name,
 		      gboolean   bold,
 		      gboolean   italics,
 		      gint       fontsize)
 {
-	PangoLayout *layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), text);
-	PangoAttrList *list = pango_layout_get_attributes (layout);
-	PangoAttribute *attr;
-
-	if (name) {
-		attr = pango_attr_family_new (name);
-		pango_attr_list_insert (list, attr);
-	}
-
-	if (bold) {
-		attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
-		pango_attr_list_insert (list, attr);
-	}
+	GdkFont *default_font = imhtml->default_font;
+	const gchar *default_name;
+	gchar **xnames;
+	gchar **pos;
+	gchar *tmp = NULL;
+	GdkFont *ret_font;
+	gchar *xname;
+	gchar **xflds;
+	gchar **newvals;
+	gchar **names = NULL;
+
+	char *italicstrings[] = {"i","o","*"};
+	int italicsind = 0, nameind = 0;
+	gboolean usebold = TRUE, usesize = TRUE, useregenc = TRUE;
+	
+	/* if we're not changing anything, use the default. this is the common case */
+	if (!name && !bold && !italics && !fontsize)
+		return gdk_font_ref (default_font);
 	
-	if (italics) {
-		attr = pango_attr_style_new (PANGO_STYLE_ITALIC);
-		pango_attr_list_insert (list, attr);
-	}
-	
-	if (fontsize) {
-		attr = pango_attr_size_new (POINT_SIZE(fontsize) * 1000);
-		pango_attr_list_insert (list, attr);
-	}
-	
-	pango_layout_set_attributes(layout, list);
-	pango_attr_list_unref(list);
-	return layout;
+	/* base things off of the default font name */
+	default_name = gtk_imhtml_get_font_name (default_font);
+	/* the default font name can actually be several names separated by ','.
+	 * This is a fontset... used in foreign encodings. */
+	do {
+		xnames = g_strsplit (default_name, ",", -1);
+		for (pos = xnames; pos && *pos; pos++) {
+			gint i, j;
+			gchar fs[10];
+			gchar *garbage;
+			xname = *pos;
+			xname = g_strchomp (xname);
+			xname = g_strchug (xname);
+			
+			xflds = g_strsplit (xname, "-", -1);
+			
+			/* figure out if we have a valid name. i wish there were an
+			 * easier way for determining how many values g_strplit gave */
+			for (i = 0; xflds [i]; i++);
+			if (i != 15) {
+				int tmp;
+				newvals = g_malloc0 (16 * sizeof (gchar *));
+				newvals [0] = "";
+				for (tmp = 1; tmp < 15; tmp++)
+					newvals [tmp] = "*";
+			} else
+				newvals = g_memdup (xflds, 16 * sizeof (xflds));
+			
+			/* we force foundry as "*" because i hate them. i should give a better reason. */
+			newvals [FNDRY] = "*";
+			
+			/* if it's "*" then it defaults to (nil) anyway. some fonts don't want (nil) */
+			if ((i > ADSTYL) && !xflds [ADSTYL][0])
+				newvals [ADSTYL] = "*";
+			
+			/* If the font doesn't work the first time, we try it with 
+			 * registry and encoding as "*" */
+			if (!useregenc) {
+				newvals [RGSTRY] = "*";
+				newvals [ENCDNG] = "*";
+			}
+			/* right. */
+			if (usebold && bold)
+				newvals [WGHT] = "bold";
+			else if (!usebold)
+				newvals [WGHT] = "*";
+			
+			if (italics)
+				/* We'll try "i" "o" to get italics and then just use "*" */
+				newvals [SLANT] = italicstrings[italicsind];
+			
+			if (usesize && fontsize) {
+				g_snprintf (fs, sizeof (fs), "%d", POINT_SIZE (fontsize));
+				newvals [PTSZ] = fs;
+				newvals [PXLSZ] = "*";
+			} else if (!usesize) {
+				newvals [PTSZ] = "*";
+				newvals [PXLSZ] = "*";
+			}
+			
+			if (name) {
+				/* we got passed a name. it might be a list of names. */
+				gchar **tmp_nms = g_strsplit (name, ",", -1);
+				for (j = 0; tmp_nms [j]; j++);
+				names = g_new0 (char *, j + 2);
+				for (j = 0; tmp_nms [j]; j++)
+					names [j] = tmp_nms [j];
+				g_free (tmp_nms);
+				/* Put the default font on the array. */
+				if (i > FMLY) {
+					names [j] = g_strdup (xflds [FMLY]);
+				}
+				newvals [FMLY] = names[nameind];
+			} else if (i > FMLY) {
+				/* we didn't get a name. we come here if the gtk font name is valid */
+				names = g_new0 (gchar *, 2);
+				names [0] = g_strdup (xflds [FMLY]);
+			} else {
+				/* we got fucked */
+				names = g_new0 (gchar *, 2);
+				names [0] = g_strdup ("*");
+			}
+			if (!tmp)
+				tmp = g_strjoinv("-", newvals);
+			else {
+				/* We have to concat the xlfds in the fontset */ 
+				garbage = tmp;
+				tmp = g_strconcat(garbage, ",", 
+						  g_strjoinv ("-", newvals), NULL); 
+				g_free(garbage);
+			}
+			g_free (newvals);
+			g_strfreev (xflds);
+		}
+		g_strfreev (xnames);
+		
+		if (default_font->type == GDK_FONT_FONT) 
+			ret_font = gdk_font_load (tmp); 
+		else {
+			/* For some reason, fontsets must end with a single * as an xlfd */
+			gchar *garbage = tmp;
+			tmp = g_strconcat(garbage, ",*", NULL);
+			ret_font = gdk_fontset_load (tmp); 
+		}
+		/* If the font didn't load, we change some of the xlfds one by one
+		 * to get the closest we can.  */
+		if (!ret_font) {
+			if (useregenc) {
+				useregenc = FALSE;
+			} else if (italics && italicsind != 2) {
+				useregenc = TRUE;
+				italicsind++;
+			} else if (bold && usebold) {
+				useregenc = TRUE;
+				italicsind=0;
+				usebold = FALSE;
+			} else if (usesize) {
+				useregenc = TRUE;        
+				italicsind = 0;
+				usebold = TRUE;
+				usesize = FALSE;
+			} else if (names && names[nameind++]) {
+				useregenc = TRUE;        
+				italicsind = 0;
+				usebold = TRUE;
+				usesize = TRUE;
+			} else {
+				ret_font = gdk_font_ref(default_font);
+			}
+		}
+		g_strfreev (names);
+		names = NULL;
+		g_free(tmp);
+		tmp=NULL;
+	} while (!ret_font); /* Loop with the new options */
+	return ret_font;
 }
 	
 static void
@@ -2365,8 +2501,7 @@
 	gint width;
 
 	if (text)
-		pango_layout_get_size(layout, &width, NULL);
-		width = PANGO_PIXELS(width);
+		width = gdk_string_width (bit->font, text);
 	else
 		width = 0;
 
@@ -2376,7 +2511,7 @@
 	li->width = width;
 	li->height = imhtml->llheight;
 	if (text)
-		li->ascent = imhtml->llascent;
+		li->ascent = MAX (imhtml->llascent, bit->font->ascent);
 	else
 		li->ascent = 0;
 	li->text = text;
@@ -2452,23 +2587,22 @@
 		gboolean seenspace = FALSE;
 		gchar *tmp;
 
-		pango_layout_get_size (bit->layout, &width, &height);
-		width = PANGO_PIXELS(width);
-		height = PANGO_PIXELS(height);
+		height = bit->font->ascent + bit->font->descent;
+		width = gdk_string_width (bit->font, bit->text);
 
 		if ((imhtml->x != 0) && ((imhtml->x + width) > imhtml->xsize)) {
 			gint remain = imhtml->xsize - imhtml->x;
-			//while (gdk_text_width (bit->font, copy, pos) < remain) {
-			//	if (copy [pos] == ' ')
-			//		seenspace = TRUE;
-			//	pos++;
+			while (gdk_text_width (bit->font, copy, pos) < remain) {
+				if (copy [pos] == ' ')
+					seenspace = TRUE;
+				pos++;
 			}
 			if (seenspace) {
 				while (copy [pos - 1] != ' ') pos--;
 
 				tmp = g_strndup (copy, pos);
 
-				backwards_update (imhtml, bit, height, 0); //bit->font->ascent);
+				backwards_update (imhtml, bit, height, bit->font->ascent);
 				add_text_renderer (imhtml, bit, tmp);
 			} else
 				pos = 0;
@@ -2476,19 +2610,18 @@
 			new_line (imhtml);
 		}
 
-	backwards_update (imhtml, bit, height, 0); //bit->font->ascent);
+		backwards_update (imhtml, bit, height, bit->font->ascent);
 
 		while (pos < strlen (bit->text)) {
-			pango_layout_get_size(bit->layout, &width, NULL);
-			width = PANGO_PIXELS(width);
+			width = gdk_string_width (bit->font, copy + pos);
 			if (imhtml->x + width > imhtml->xsize) {
 				gint newpos = 0;
 				gint remain = imhtml->xsize - imhtml->x;
-				//while (gdk_text_width (bit->font, copy + pos, newpos) < remain) {
-				//	if (copy [pos + newpos] == ' ')
-				//		seenspace = TRUE;
-				//	newpos++;
-				//}
+				while (gdk_text_width (bit->font, copy + pos, newpos) < remain) {
+					if (copy [pos + newpos] == ' ')
+						seenspace = TRUE;
+					newpos++;
+				}
 
 				if (seenspace)
 					while (copy [pos + newpos - 1] != ' ') newpos--;
@@ -2499,7 +2632,7 @@
 				tmp = g_strndup (copy + pos, newpos);
 				pos += newpos;
 
-				backwards_update (imhtml, bit, height, 0); //bit->font->ascent);
+				backwards_update (imhtml, bit, height, bit->font->ascent);
 				add_text_renderer (imhtml, bit, tmp);
 
 				seenspace = FALSE;
@@ -2507,7 +2640,7 @@
 			} else {
 				tmp = g_strdup (copy + pos);
 
-				backwards_update (imhtml, bit, height, 0); //bit->font->ascent);
+				backwards_update (imhtml, bit, height, bit->font->ascent);
 				add_text_renderer (imhtml, bit, tmp);
 
 				pos = strlen (bit->text);
@@ -2659,15 +2792,15 @@
 	if ((font != NULL) || bold || italics || pre) {
 		if (font && (bold || italics || font->size || font->face || pre)) {
 			if (pre) {
-				bit->layout = gtk_imhtml_font_load (bit->text, imhtml, DEFAULT_PRE_FACE, bold, italics, font->size);
+				bit->font = gtk_imhtml_font_load (imhtml, DEFAULT_PRE_FACE, bold, italics, font->size);
 			} else {
-				bit->layout = gtk_imhtml_font_load (bit->text, imhtml, font->face, bold, italics, font->size);
+				bit->font = gtk_imhtml_font_load (imhtml, font->face, bold, italics, font->size);
 			}
 		} else if (bold || italics || pre) {
 			if (pre) {
-				bit->layout = gtk_imhtml_font_load (bit->text, imhtml, DEFAULT_PRE_FACE, bold, italics, 0);
+				bit->font = gtk_imhtml_font_load (imhtml, DEFAULT_PRE_FACE, bold, italics, 0);
 			} else {
-				bit->layout = gtk_imhtml_font_load (bit->text, imhtml, NULL, bold, italics, 0);
+				bit->font = gtk_imhtml_font_load (imhtml, NULL, bold, italics, 0);
 			}
 		}
 
@@ -2681,8 +2814,8 @@
 	}
 
 	if (((bit->type == TYPE_TEXT) || (bit->type == TYPE_SMILEY) || (bit->type == TYPE_COMMENT)) &&
-	    (bit->layout == NULL))
-		return NULL;
+	    (bit->font == NULL))
+		bit->font = gdk_font_ref (imhtml->default_font);
 
 	if (bg != NULL)
 		bit->bg = gdk_color_copy (bg);
@@ -3517,8 +3650,8 @@
 		imhtml->bits = g_list_remove (imhtml->bits, bit);
 		if (bit->text)
 			g_free (bit->text);
-		if (bit->layout)
-			g_object_unref (bit->layout);
+		if (bit->font)
+			gdk_font_unref (bit->font);
 		if (bit->fore)
 			gdk_color_free (bit->fore);
 		if (bit->back)