Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
Main Page
Related Pages
Data Structures
Files
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Pages
special.c
Go to the documentation of this file.
1
/*
2
* Copyright (C) 2000, Matias Atria
3
*
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
*/
18
19
#include <config.h>
20
#include <ctype.h>
21
#include <string.h>
22
23
#include "
mdvi.h
"
24
#include "
private.h
"
25
26
#if defined(WITH_REGEX_SPECIALS) && defined(HAVE_REGEX_H)
27
#include <regex.h>
28
#endif
29
30
typedef
struct
_DviSpecial
{
31
struct
_DviSpecial
*
next
;
32
struct
_DviSpecial
*
prev
;
33
char
*
label
;
34
char
*
prefix
;
35
size_t
plen
;
36
#ifdef WITH_REGEX_SPECIALS
37
regex_t reg;
38
int
has_reg;
39
#endif
40
DviSpecialHandler
handler
;
41
}
DviSpecial
;
42
43
static
ListHead
specials
= {NULL, NULL, 0};
44
45
#define SPECIAL(x) \
46
void x __PROTO((DviContext *, const char *, const char *))
47
48
static
SPECIAL
(
sp_layer
);
49
extern
SPECIAL
(
epsf_special
);
50
extern
SPECIAL
(do_color_special);
51
52
static
struct
{
53
char
*
label
;
54
char
*
prefix
;
55
char
*
regex
;
56
DviSpecialHandler
handler
;
57
}
builtins
[] = {
58
{
"Layers"
,
"layer"
, NULL,
sp_layer
},
59
{
"EPSF"
,
"psfile"
, NULL,
epsf_special
}
60
};
61
#define NSPECIALS (sizeof(builtins) / sizeof(builtins[0]))
62
static
int
registered_builtins
= 0;
63
64
static
void
register_builtin_specials
(
void
)
65
{
66
int
i;
67
68
ASSERT
(
registered_builtins
== 0);
69
registered_builtins
= 1;
70
for
(i = 0; i <
NSPECIALS
; i++)
71
mdvi_register_special
(
72
builtins
[i].
label
,
73
builtins
[i].
prefix
,
74
builtins
[i].
regex
,
75
builtins
[i].
handler
,
76
1
/* replace if exists */
);
77
}
78
79
static
DviSpecial
*
find_special_prefix
(
const
char
*
prefix
)
80
{
81
DviSpecial
*sp;
82
83
/* should have a hash table here, but I'm so lazy */
84
for
(sp = (
DviSpecial
*)specials.
head
; sp; sp = sp->
next
) {
85
if
(
STRCEQ
(sp->
prefix
, prefix))
86
break
;
87
}
88
return
sp;
89
}
90
91
int
mdvi_register_special
(
const
char
*
label
,
const
char
*
prefix
,
92
const
char
*
regex
, DviSpecialHandler
handler
,
int
replace)
93
{
94
DviSpecial
*sp;
95
int
newsp = 0;
96
97
if
(!
registered_builtins
)
98
register_builtin_specials
();
99
100
sp =
find_special_prefix
(prefix);
101
if
(sp == NULL) {
102
sp =
xalloc
(
DviSpecial
);
103
sp->
prefix
=
mdvi_strdup
(prefix);
104
newsp = 1;
105
}
else
if
(!replace)
106
return
-1;
107
else
{
108
mdvi_free
(sp->
label
);
109
sp->
label
= NULL;
110
}
111
112
#ifdef WITH_REGEX_SPECIALS
113
if
(!newsp && sp->has_reg) {
114
regfree(&sp->reg);
115
sp->has_reg = 0;
116
}
117
if
(regex && regcomp(&sp->reg, regex, REG_NOSUB) != 0) {
118
if
(newsp) {
119
mdvi_free
(sp->
prefix
);
120
mdvi_free
(sp);
121
}
122
return
-1;
123
}
124
sp->has_reg = (regex != NULL);
125
#endif
126
sp->
handler
=
handler
;
127
sp->
label
=
mdvi_strdup
(label);
128
sp->
plen
= strlen(prefix);
129
if
(newsp)
130
listh_prepend
(&specials,
LIST
(sp));
131
DEBUG
((
DBG_SPECIAL
,
132
"New \\special handler `%s' with prefix `%s'\n"
,
133
label, prefix));
134
return
0;
135
}
136
137
int
mdvi_unregister_special
(
const
char
*
prefix
)
138
{
139
DviSpecial
*sp;
140
141
sp =
find_special_prefix
(prefix);
142
if
(sp == NULL)
143
return
-1;
144
mdvi_free
(sp->
prefix
);
145
#ifdef WITH_REGEX_SPECIALS
146
if
(sp->has_reg)
147
regfree(&sp->reg);
148
#endif
149
listh_remove
(&specials,
LIST
(sp));
150
mdvi_free
(sp);
151
return
0;
152
}
153
154
#define IS_PREFIX_DELIMITER(x) (strchr(" \t\n:=", (x)) != NULL)
155
156
int
mdvi_do_special
(
DviContext
*dvi,
char
*
string
)
157
{
158
char
*
prefix
;
159
char
*ptr;
160
DviSpecial
*sp;
161
162
if
(!
registered_builtins
) {
163
}
164
165
if
(!
string
|| !*
string
)
166
return
0;
167
168
/* skip leading spaces */
169
while
(*
string
&& isspace(*
string
))
170
string
++;
171
172
DEBUG
((
DBG_SPECIAL
,
"Looking for a handler for `%s'\n"
,
string
));
173
174
/* now try to find a match */
175
ptr = string;
176
for
(sp = (
DviSpecial
*)specials.
head
; sp; sp = sp->
next
) {
177
#ifdef WITH_REGEX_SPECIALS
178
if
(sp->has_reg && !regexec(&sp->reg, ptr, 0, 0, 0))
179
break
;
180
#endif
181
/* check the prefix */
182
if
(
STRNCEQ
(sp->
prefix
, ptr, sp->
plen
)) {
183
ptr += sp->
plen
;
184
break
;
185
}
186
}
187
188
if
(sp == NULL) {
189
DEBUG
((
DBG_SPECIAL
,
"None found\n"
));
190
return
-1;
191
}
192
193
/* extract the prefix */
194
if
(ptr ==
string
) {
195
prefix = NULL;
196
DEBUG
((
DBG_SPECIAL
,
197
"REGEX match with `%s' (arg `%s')\n"
,
198
sp->
label
, ptr));
199
}
else
{
200
if
(*ptr) *ptr++ = 0;
201
prefix = string;
202
DEBUG
((
DBG_SPECIAL
,
203
"PREFIX match with `%s' (prefix `%s', arg `%s')\n"
,
204
sp->
label
, prefix, ptr));
205
}
206
207
/* invoke the handler */
208
sp->
handler
(dvi, prefix, ptr);
209
210
return
0;
211
}
212
213
void
mdvi_flush_specials
(
void
)
214
{
215
DviSpecial
*sp, *list;
216
217
218
for
(list = (
DviSpecial
*)specials.
head
; (sp = list); ) {
219
list = sp->
next
;
220
if
(sp->
prefix
)
mdvi_free
(sp->
prefix
);
221
if
(sp->
label
)
mdvi_free
(sp->
label
);
222
#ifdef WITH_REGEX_SPECIALS
223
if
(sp->has_reg)
224
regfree(&sp->reg);
225
#endif
226
mdvi_free
(sp);
227
}
228
specials.
head
= NULL;
229
specials.
tail
= NULL;
230
specials.
count
= 0;
231
}
232
233
/* some builtin specials */
234
235
void
sp_layer
(
DviContext
*dvi,
const
char
*
prefix
,
const
char
*arg)
236
{
237
if
(
STREQ
(
"push"
, arg))
238
dvi->
curr_layer
++;
239
else
if
(
STREQ
(
"pop"
, arg)) {
240
if
(dvi->
curr_layer
)
241
dvi->
curr_layer
--;
242
else
243
mdvi_warning
(
_
(
"%s: tried to pop top level layer\n"
),
244
dvi->
filename
);
245
}
else
if
(
STREQ
(
"reset"
, arg))
246
dvi->
curr_layer
= 0;
247
DEBUG
((
DBG_SPECIAL
,
"Layer level: %d\n"
, dvi->
curr_layer
));
248
}
249
evince-master
backend
dvi
mdvi-lib
special.c
Generated on Thu Jul 13 2017 13:41:44 for Evince by
1.8.4