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

📄 viewer-win32.c

📁 GTK+-2.0源码之pango-1.15.6.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Pango * viewer-win32.c: Example program to view a UTF-8 encoding file *                 using Pango to render result. * * Copyright (C) 1999 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 <gtk/gtk.h>#include <gdk/win32/gdkwin32.h>#include <pango/pango.h>#include <pango/pangowin32.h>#include <errno.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#define BUFSIZE 1024typedef struct _Paragraph Paragraph;/* Structure representing a paragraph */struct _Paragraph {  char *text;  int length;  int height;   /* Height, in pixels */  PangoLayout *layout;};GList *paragraphs;static PangoFontDescription *font_description;static Paragraph *highlight_para;static int highlight_offset;GtkWidget *styles_combo;static GtkWidget *message_label;GtkWidget *layout;PangoContext *context;static void fill_styles_combo (GtkWidget *combo);/* Read an entire file into a string */static char *read_file(char *name){  GString *inbuf;  FILE *file;  char *text;  char buffer[BUFSIZE];  file = fopen (name, "r");  if (!file)    {      fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname (), name);      return NULL;    }  inbuf = g_string_new (NULL);  while (1)    {      char *bp = fgets (buffer, BUFSIZE-1, file);      if (ferror (file))	{	  fprintf (stderr, "%s: Error reading %s\n", g_get_prgname (), name);	  g_string_free (inbuf, TRUE);	  return NULL;	}      else if (bp == NULL)	break;      g_string_append (inbuf, buffer);    }  fclose (file);  text = inbuf->str;  g_string_free (inbuf, FALSE);  return text;}/* Take a UTF8 string and break it into paragraphs on \n characters */static GList *split_paragraphs (char *text){  char *p = text;  char *next;  gunichar wc;  GList *result = NULL;  char *last_para = text;  while (*p)    {      wc = g_utf8_get_char (p);      next = g_utf8_next_char (p);      if (wc == (gunichar)-1)	{	  fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ());	  g_list_foreach (result, (GFunc)g_free, NULL);	  return NULL;	}      if (!*p || !wc || wc == '\n')	{	  Paragraph *para = g_new (Paragraph, 1);	  para->text = last_para;	  para->length = p - last_para;	  para->layout = pango_layout_new (context);	  pango_layout_set_text (para->layout, para->text, para->length);	  para->height = 0;	  last_para = next;	  result = g_list_prepend (result, para);	}      if (!wc) /* incomplete character at end */	break;      p = next;    }  return g_list_reverse (result);}/* Given an x-y position, return the paragraph and offset * within the paragraph of the click. */gbooleanxy_to_cp (int width, int x, int y, Paragraph **para_return, int *index){  GList *para_list;  int height = 0;  *para_return = NULL;  para_list = paragraphs;  while (para_list && height < y)    {      Paragraph *para = para_list->data;      if (height + para->height >= y)	{	  gboolean result = pango_layout_xy_to_index (para->layout,						      x * PANGO_SCALE,						      (y - height) * PANGO_SCALE,						      index, NULL);	  if (result && para_return)	    *para_return = para;	  return result;	}      height += para->height;      para_list = para_list->next;    }  return FALSE;}/* Given a paragraph and offset in that paragraph, find the * bounding rectangle for the character at the offset. */voidchar_bounds (Paragraph *para, int index, int width, PangoRectangle *rect){  GList *para_list;  int height = 0;  para_list = paragraphs;  while (para_list)    {      Paragraph *cur_para = para_list->data;      if (cur_para == para)	{	  PangoRectangle pos;	  pango_layout_index_to_pos (cur_para->layout, index, &pos);	  rect->x = PANGO_PIXELS (MIN (pos.x, pos.x + pos.width));	  rect->width = PANGO_PIXELS (ABS (pos.width));	  rect->y = height + PANGO_PIXELS (pos.y);	  rect->height = PANGO_PIXELS (pos.height);	}      height += cur_para->height;      para_list = para_list->next;    }}/* XOR a rectangle over a given character */voidxor_char (GtkWidget *layout, GdkRectangle *clip_rect,	  Paragraph *para, int offset){  static GdkGC *gc;  PangoRectangle rect;		/* GdkRectangle in 1.2 is too limited				 */  if (!gc)    {      GdkGCValues values;      values.foreground = layout->style->white.pixel ?	layout->style->white : layout->style->black;      values.function = GDK_XOR;      gc = gdk_gc_new_with_values (GTK_LAYOUT (layout)->bin_window,				   &values,				   GDK_GC_FOREGROUND | GDK_GC_FUNCTION);    }  gdk_gc_set_clip_rectangle (gc, clip_rect);  char_bounds (para, offset, layout->allocation.width, &rect);  rect.y -= GTK_LAYOUT (layout)->yoffset;  if ((rect.y + rect.height >= 0) && (rect.y < layout->allocation.height))    gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, gc, TRUE,			rect.x, rect.y, rect.width, rect.height);}/* Handle a size allocation by re-laying-out each paragraph to * the new width, setting the new size for the layout and * then queing a redraw */voidsize_allocate (GtkWidget *layout, GtkAllocation *allocation){  GList *tmp_list;  guint height = 0;  PangoDirection base_dir = pango_context_get_base_dir (context);  tmp_list = paragraphs;  while (tmp_list)    {      Paragraph *para = tmp_list->data;      PangoRectangle logical_rect;      tmp_list = tmp_list->next;      pango_layout_set_alignment (para->layout,				  base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT);      pango_layout_set_width (para->layout, layout->allocation.width * PANGO_SCALE);      pango_layout_get_extents (para->layout, NULL, &logical_rect);      para->height = PANGO_PIXELS (logical_rect.height);      height += para->height;    }  gtk_layout_set_size (GTK_LAYOUT (layout), allocation->width, height);  if (GTK_LAYOUT (layout)->yoffset + allocation->height > height)    gtk_adjustment_set_value (GTK_LAYOUT (layout)->vadjustment, (float)(height - allocation->height));}/* Handle a draw/expose by finding the paragraphs that intersect * the region and reexposing them. */voiddraw (GtkWidget *layout, GdkRectangle *area){  GList *tmp_list;  guint height = 0;  HDC hdc;  const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND|GDK_GC_FONT;  gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window,		      layout->style->base_gc[layout->state],		      TRUE,		      area->x, area->y,		      area->width, area->height);  gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], area);  hdc = gdk_win32_hdc_get (GTK_LAYOUT (layout)->bin_window,			   layout->style->text_gc[GTK_STATE_NORMAL],			   mask);  tmp_list = paragraphs;  while (tmp_list &&	 height < area->y + area->height + GTK_LAYOUT (layout)->yoffset)    {      Paragraph *para = tmp_list->data;      tmp_list = tmp_list->next;      if (height + para->height >= GTK_LAYOUT (layout)->yoffset + area->y)	pango_win32_render_layout (hdc, para->layout,				   0, height - GTK_LAYOUT (layout)->yoffset);      height += para->height;    }  gdk_win32_hdc_release (GTK_LAYOUT (layout)->bin_window,			 layout->style->text_gc[GTK_STATE_NORMAL],			 mask);  gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], NULL);  if (highlight_para)    xor_char (layout, area, highlight_para, highlight_offset);}gbooleanexpose (GtkWidget *layout, GdkEventExpose *event){  if (event->window == GTK_LAYOUT (layout)->bin_window)    draw (layout, &event->area);  return TRUE;}voidbutton_press (GtkWidget *layout, GdkEventButton *event){  Paragraph *para = NULL;  int offset;  gchar *message;  xy_to_cp (layout->allocation.width,	    event->x, event->y + GTK_LAYOUT (layout)->yoffset,	    &para, &offset);  if (highlight_para)    xor_char (layout, NULL, highlight_para, highlight_offset);  highlight_para = para;  highlight_offset = offset;  if (para)    {      gunichar wc;      wc = g_utf8_get_char (para->text + offset);      message = g_strdup_printf ("Current char: U%04x", wc);      xor_char (layout, NULL, highlight_para, highlight_offset);    }  else    message = g_strdup_printf ("Current char:");  gtk_label_set_text (GTK_LABEL (message_label), message);  g_free (message);}static voidcheckbutton_toggled (GtkWidget *widget, gpointer data){  GList *para_list;  pango_context_set_base_dir (context, GTK_TOGGLE_BUTTON (widget)->active ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);  para_list = paragraphs;  while (para_list)    {      Paragraph *para = para_list->data;

⌨️ 快捷键说明

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