⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pango-markup.c

📁 Pango is a library for layout and rendering of text, with an emphasis on internationalization. Pang
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Pango * pango-markup.c: Parse markup into attributed text * * Copyright (C) 2000 Red Hat Software * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <config.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include "pango-attributes.h"#include "pango-font.h"#include "pango-enum-types.h"#include "pango-impl-utils.h"/* FIXME */#define _(x) x/* CSS size levels */typedef enum{  XXSmall = -3,  XSmall = -2,  Small = -1,  Medium = 0,  Large = 1,  XLarge = 2,  XXLarge = 3} SizeLevel;typedef struct _MarkupData MarkupData;struct _MarkupData{  PangoAttrList *attr_list;  GString *text;  GSList *tag_stack;  gsize index;  GSList *to_apply;  gunichar accel_marker;  gunichar accel_char;};typedef struct _OpenTag OpenTag;struct _OpenTag{  GSList *attrs;  gsize start_index;  /* Current total scale level; reset whenever   * an absolute size is set.   * Each "larger" ups it 1, each "smaller" decrements it 1   */  gint scale_level;  /* Our impact on scale_level, so we know whether we   * need to create an attribute ourselves on close   */  gint scale_level_delta;  /* Base scale factor currently in effect   * or size that this tag   * forces, or parent's scale factor or size.   */  double base_scale_factor;  int base_font_size;  guint has_base_font_size : 1;};typedef gboolean (*TagParseFunc) (MarkupData            *md,				  OpenTag               *tag,				  const gchar          **names,				  const gchar          **values,				  GMarkupParseContext   *context,				  GError               **error);static gboolean b_parse_func        (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean big_parse_func      (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean span_parse_func     (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean i_parse_func        (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean markup_parse_func   (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean s_parse_func        (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean sub_parse_func      (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean sup_parse_func      (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean small_parse_func    (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean tt_parse_func       (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static gboolean u_parse_func        (MarkupData           *md,				     OpenTag              *tag,				     const gchar         **names,				     const gchar         **values,				     GMarkupParseContext  *context,				     GError              **error);static doublescale_factor (int scale_level, double base){  double factor = base;  int i;  /* 1.2 is the CSS scale factor between sizes */  if (scale_level > 0)    {      i = 0;      while (i < scale_level)	{	  factor *= 1.2;	  ++i;	}    }  else if (scale_level < 0)    {      i = scale_level;      while (i < 0)	{	  factor /= 1.2;	  ++i;	}    }  return factor;}static voidopen_tag_free (OpenTag *ot){  g_slist_foreach (ot->attrs, (GFunc) pango_attribute_destroy, NULL);  g_slist_free (ot->attrs);  g_slice_free (OpenTag, ot);}static voidopen_tag_set_absolute_font_size (OpenTag *ot,				 int      font_size){  ot->base_font_size = font_size;  ot->has_base_font_size = TRUE;  ot->scale_level = 0;  ot->scale_level_delta = 0;}static voidopen_tag_set_absolute_font_scale (OpenTag *ot,				  double   scale){  ot->base_scale_factor = scale;  ot->has_base_font_size = FALSE;  ot->scale_level = 0;  ot->scale_level_delta = 0;}static OpenTag*markup_data_open_tag (MarkupData   *md){  OpenTag *ot;  OpenTag *parent = NULL;  if (md->attr_list == NULL)    return NULL;  if (md->tag_stack)    parent = md->tag_stack->data;  ot = g_slice_new (OpenTag);  ot->attrs = NULL;  ot->start_index = md->index;  ot->scale_level_delta = 0;  if (parent == NULL)    {      ot->base_scale_factor = 1.0;      ot->base_font_size = 0;      ot->has_base_font_size = FALSE;      ot->scale_level = 0;    }  else    {      ot->base_scale_factor = parent->base_scale_factor;      ot->base_font_size = parent->base_font_size;      ot->has_base_font_size = parent->has_base_font_size;      ot->scale_level = parent->scale_level;    }  md->tag_stack = g_slist_prepend (md->tag_stack, ot);  return ot;}static voidmarkup_data_close_tag (MarkupData *md){  OpenTag *ot;  GSList *tmp_list;  if (md->attr_list == NULL)    return;  /* pop the stack */  ot = md->tag_stack->data;  md->tag_stack = g_slist_delete_link (md->tag_stack,				       md->tag_stack);  /* Adjust end indexes, and push each attr onto the front of the   * to_apply list. This means that outermost tags are on the front of   * that list; if we apply the list in order, then the innermost   * tags will "win" which is correct.   */  tmp_list = ot->attrs;  while (tmp_list != NULL)    {      PangoAttribute *a = tmp_list->data;      a->start_index = ot->start_index;      a->end_index = md->index;      md->to_apply = g_slist_prepend (md->to_apply, a);      tmp_list = g_slist_next (tmp_list);    }  if (ot->scale_level_delta != 0)    {      /* We affected relative font size; create an appropriate       * attribute and reverse our effects on the current level       */      PangoAttribute *a;      if (ot->has_base_font_size)	{	  /* Create a font using the absolute point size	   * as the base size to be scaled from	   */	  a = pango_attr_size_new (scale_factor (ot->scale_level,						 1.0) *				   ot->base_font_size);	}      else	{	  /* Create a font using the current scale factor	   * as the base size to be scaled from	   */	  a = pango_attr_scale_new (scale_factor (ot->scale_level,						  ot->base_scale_factor));	}      a->start_index = ot->start_index;      a->end_index = md->index;      md->to_apply = g_slist_prepend (md->to_apply, a);    }  g_slist_free (ot->attrs);  g_slice_free (OpenTag, ot);}static voidstart_element_handler  (GMarkupParseContext *context,			const gchar         *element_name,			const gchar        **attribute_names,			const gchar        **attribute_values,			gpointer             user_data,			GError             **error){  TagParseFunc parse_func = NULL;  OpenTag *ot;  switch (*element_name)    {    case 'b':      if (strcmp ("b", element_name) == 0)	parse_func = b_parse_func;      else if (strcmp ("big", element_name) == 0)	parse_func = big_parse_func;      break;    case 'i':      if (strcmp ("i", element_name) == 0)	parse_func = i_parse_func;      break;    case 'm':      if (strcmp ("markup", element_name) == 0)	parse_func = markup_parse_func;      break;    case 's':      if (strcmp ("span", element_name) == 0)	parse_func = span_parse_func;      else if (strcmp ("s", element_name) == 0)	parse_func = s_parse_func;      else if (strcmp ("sub", element_name) == 0)	parse_func = sub_parse_func;      else if (strcmp ("sup", element_name) == 0)	parse_func = sup_parse_func;      else if (strcmp ("small", element_name) == 0)	parse_func = small_parse_func;      break;    case 't':      if (strcmp ("tt", element_name) == 0)	parse_func = tt_parse_func;      break;    case 'u':      if (strcmp ("u", element_name) == 0)	parse_func = u_parse_func;      break;    }  if (parse_func == NULL)    {      gint line_number, char_number;      g_markup_parse_context_get_position (context,					   &line_number, &char_number);      g_set_error (error,		   G_MARKUP_ERROR,		   G_MARKUP_ERROR_UNKNOWN_ELEMENT,		   _("Unknown tag '%s' on line %d char %d"),		   element_name,		   line_number, char_number);      return;    }  ot = markup_data_open_tag (user_data);  /* note ot may be NULL if the user didn't want the attribute list */  if (!(*parse_func) (user_data, ot,		      attribute_names, attribute_values,		      context, error))    {      /* there's nothing to do; we return an error, and end up       * freeing ot off the tag stack later.       */    }}static voidend_element_handler    (GMarkupParseContext *context,			const gchar         *element_name,			gpointer             user_data,			GError             **error){  markup_data_close_tag (user_data);}static voidtext_handler           (GMarkupParseContext *context,			const gchar         *text,			gsize                text_len,			gpointer             user_data,			GError             **error){  MarkupData *md = user_data;  if (md->accel_marker == 0)    {      /* Just append all the text */      md->index += text_len;      g_string_append_len (md->text, text, text_len);    }  else    {      /* Parse the accelerator */      const gchar *p;      const gchar *end;      const gchar *range_start;      const gchar *range_end;      gssize uline_index = -1;      gsize uline_len = 0;	/* Quiet GCC */      range_end = NULL;      range_start = text;      p = text;      end = text + text_len;      while (p != end)	{	  gunichar c;	  c = g_utf8_get_char (p);	  if (range_end)	    {	      if (c == md->accel_marker)		{		  /* escaped accel marker; move range_end		   * past the accel marker that came before,		   * append the whole thing		   */		  range_end = g_utf8_next_char (range_end);		  g_string_append_len (md->text,				       range_start,				       range_end - range_start);		  md->index += range_end - range_start;		  /* set next range_start, skipping accel marker */		  range_start = g_utf8_next_char (p);		}	      else		{		  /* Don't append the accel marker (leave range_end		   * alone); set the accel char to c; record location for		   * underline attribute		   */		  if (md->accel_char == 0)		    md->accel_char = c;		  g_string_append_len (md->text,				       range_start,				       range_end - range_start);		  md->index += range_end - range_start;		  /* The underline should go underneath the char		   * we're setting as the next range_start		   */		  uline_index = md->index;		  uline_len = g_utf8_next_char (p) - p;		  /* set next range_start to include this char */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -