📄 pango-utils.c
字号:
/* Pango * pango-utils.c: Utilities for internal functions and modules * * 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 <errno.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <locale.h>#include "pango-font.h"#include "pango-features.h"#include "pango-impl-utils.h"#include <glib/gstdio.h>#include "mini-fribidi/fribidi.h"#ifndef HAVE_FLOCKFILE# define flockfile(f) (void)1# define funlockfile(f) (void)1# define getc_unlocked(f) getc(f)#endif /* !HAVE_FLOCKFILE */#ifdef G_OS_WIN32#include <sys/types.h>#define STRICT#include <windows.h>#endifstruct PangoAlias{ char *alias; int n_families; char **families; gboolean visible; /* Do we want/need this? */};static GHashTable *pango_aliases_ht = NULL;PangoWarningHistory _pango_warning_history = { FALSE, FALSE, FALSE };/** * pango_version: * * This is similar to the macro %PANGO_VERSION except that * it returns the encoded version of Pango available at run-time, * as opposed to the version available at compile-time. * * A version number can be encoded into an integer using * PANGO_VERSION_ENCODE(). * * Returns value: The encoded version of Pango library * available at run time. * * Since: 1.16 **/intpango_version (void){ return PANGO_VERSION;}/** * pango_version_string: * * This is similar to the macro %PANGO_VERSION_STRING except that * it returns the version of Pango available at run-time, as opposed to * the version available at compile-time. * * Returns value: A string containing the version of Pango library * available at run time. * The returned string is owned by Pango and should not be modified * or freed. * * Since: 1.16 **/const char *pango_version_string (void){ return PANGO_VERSION_STRING;}/** * pango_version_check: * @required_major: the required major version. * @required_minor: the required minor version. * @required_micro: the required major version. * * Checks that the Pango library in use is compatible with the * given version. Generally you would pass in the constants * %PANGO_VERSION_MAJOR, %PANGO_VERSION_MINOR, %PANGO_VERSION_MICRO * as the three arguments to this function; that produces * a check that the library in use at run-time is compatible with * the version of Pango the application or module was compiled against. * * Compatibility is defined by two things: first the version * of the running library is newer than the version * @required_major.required_minor.@required_micro. Second * the running library must be binary compatible with the * version @required_major.required_minor.@required_micro * (same major version.) * * For compile-time version checking use PANGO_VERSION_CHECK(). * * Return value: %NULL if the Pango library is compatible with the * given version, or a string describing the version mismatch. * The returned string is owned by Pango and should not be modified * or freed. * * Since: 1.16 **/const gchar*pango_version_check (int required_major, int required_minor, int required_micro){ gint pango_effective_micro = 100 * PANGO_VERSION_MINOR + PANGO_VERSION_MICRO; gint required_effective_micro = 100 * required_minor + required_micro; if (required_major < PANGO_VERSION_MAJOR) return "Pango version too new (major mismatch)"; if (required_effective_micro < pango_effective_micro - PANGO_BINARY_AGE) return "Pango version too new (micro mismatch)"; if (required_effective_micro > pango_effective_micro) return "Pango version too old (micro mismatch)"; return NULL;}/** * pango_trim_string: * @str: a string * * Trims leading and trailing whitespace from a string. * * Return value: A newly-allocated string that must be freed with g_free() **/char *pango_trim_string (const char *str){ int len; g_return_val_if_fail (str != NULL, NULL); while (*str && g_ascii_isspace (*str)) str++; len = strlen (str); while (len > 0 && g_ascii_isspace (str[len-1])) len--; return g_strndup (str, len);}/** * pango_split_file_list: * @str: a %G_SEARCHPATH_SEPARATOR separated list of filenames * * Splits a %G_SEARCHPATH_SEPARATOR-separated list of files, stripping * white space and substituting ~/ with $HOME/. * * Return value: a list of strings to be freed with g_strfreev() **/char **pango_split_file_list (const char *str){ int i = 0; int j; char **files; files = g_strsplit (str, G_SEARCHPATH_SEPARATOR_S, -1); while (files[i]) { char *file = pango_trim_string (files[i]); /* If the resulting file is empty, skip it */ if (file[0] == '\0') { g_free(file); g_free (files[i]); for (j = i + 1; files[j]; j++) files[j - 1] = files[j]; files[j - 1] = NULL; continue; }#ifndef G_OS_WIN32 /* '~' is a quite normal and common character in file names on * Windows, especially in the 8.3 versions of long file names, which * still occur now and then. Also, few Windows user are aware of the * Unix shell convention that '~' stands for the home directory, * even if they happen to have a home directory. */ if (file[0] == '~' && file[1] == G_DIR_SEPARATOR) { char *tmp = g_strconcat (g_get_home_dir(), file + 1, NULL); g_free (file); file = tmp; } else if (file[0] == '~' && file[1] == '\0') { g_free (file); file = g_strdup (g_get_home_dir()); }#endif g_free (files[i]); files[i] = file; i++; } return files;}/** * pango_read_line: * @stream: a stdio stream * @str: #GString buffer into which to write the result * * Reads an entire line from a file into a buffer. Lines may * be delimited with '\n', '\r', '\n\r', or '\r\n'. The delimiter * is not written into the buffer. Text after a '#' character is treated as * a comment and skipped. '\' can be used to escape a # character. * '\' proceeding a line delimiter combines adjacent lines. A '\' proceeding * any other character is ignored and written into the output buffer * unmodified. * * Return value: 0 if the stream was already at an %EOF character, otherwise * the number of lines read (this is useful for maintaining * a line number counter which doesn't combine lines with '\') **/gintpango_read_line (FILE *stream, GString *str){ gboolean quoted = FALSE; gboolean comment = FALSE; int n_read = 0; int lines = 1; flockfile (stream); g_string_truncate (str, 0); while (1) { int c; c = getc_unlocked (stream); if (c == EOF) { if (quoted) g_string_append_c (str, '\\'); goto done; } else n_read++; if (quoted) { quoted = FALSE; switch (c) { case '#': g_string_append_c (str, '#'); break; case '\r': case '\n': { int next_c = getc_unlocked (stream); if (!(next_c == EOF || (c == '\r' && next_c == '\n') || (c == '\n' && next_c == '\r'))) ungetc (next_c, stream); lines++; break; } default: g_string_append_c (str, '\\'); g_string_append_c (str, c); } } else { switch (c) { case '#': comment = TRUE; break; case '\\': if (!comment) quoted = TRUE; break; case '\n': { int next_c = getc_unlocked (stream); if (!(c == EOF || (c == '\r' && next_c == '\n') || (c == '\n' && next_c == '\r'))) ungetc (next_c, stream); goto done; } default: if (!comment) g_string_append_c (str, c); } } } done: funlockfile (stream); return (n_read > 0) ? lines : 0;}/** * pango_skip_space: * @pos: in/out string position * * Skips 0 or more characters of white space. * * Return value: %FALSE if skipping the white space leaves * the position at a '\0' character. **/gbooleanpango_skip_space (const char **pos){ const char *p = *pos; while (g_ascii_isspace (*p)) p++; *pos = p; return !(*p == '\0');}/** * pango_scan_word: * @pos: in/out string position * @out: a #GString into which to write the result * * Scans a word into a #GString buffer. A word consists * of [A-Za-z_] followed by zero or more [A-Za-z_0-9] * Leading white space is skipped. * * Return value: %FALSE if a parse error occurred. **/gbooleanpango_scan_word (const char **pos, GString *out){ const char *p = *pos; while (g_ascii_isspace (*p)) p++; if (!((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || *p == '_')) return FALSE; g_string_truncate (out, 0); g_string_append_c (out, *p); p++; while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_') { g_string_append_c (out, *p); p++; } *pos = p; return TRUE;}/** * pango_scan_string: * @pos: in/out string position * @out: a #GString into which to write the result * * Scans a string into a #GString buffer. The string may either * be a sequence of non-white-space characters, or a quoted * string with '"'. Instead a quoted string, '\"' represents * a literal quote. Leading white space outside of quotes is skipped. * * Return value: %FALSE if a parse error occurred. **/gbooleanpango_scan_string (const char **pos, GString *out){ const char *p = *pos; while (g_ascii_isspace (*p)) p++; if (!*p) return FALSE; else if (*p == '"') { gboolean quoted = FALSE; g_string_truncate (out, 0); p++; while (TRUE) { if (quoted) { int c = *p; switch (c) { case '\0': return FALSE; case 'n': c = '\n'; break; case 't': c = '\t'; break; default: break; } quoted = FALSE; g_string_append_c (out, c); } else { switch (*p) { case '\0': return FALSE; case '\\': quoted = TRUE; break; case '"': p++; goto done; default: g_string_append_c (out, *p); break; } } p++; } done: ; } else { g_string_truncate (out, 0); while (*p && !g_ascii_isspace (*p)) { g_string_append_c (out, *p); p++; } } *pos = p; return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -