Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 1 | /***************************************************************************/ |
| 2 | /* */ |
| 3 | /* z1gload.c */ |
| 4 | /* */ |
| 5 | /* Experimental Type 1 Glyph Loader (body). */ |
| 6 | /* */ |
| 7 | /* Copyright 1996-2000 by */ |
| 8 | /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
| 9 | /* */ |
| 10 | /* This file is part of the FreeType project, and may only be used, */ |
| 11 | /* modified, and distributed under the terms of the FreeType project */ |
| 12 | /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
| 13 | /* this file you indicate that you have read the license and */ |
| 14 | /* understand and accept it fully. */ |
| 15 | /* */ |
| 16 | /***************************************************************************/ |
| 17 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 18 | |
David Turner | a90663f | 2000-07-08 00:41:13 +0000 | [diff] [blame] | 19 | #ifdef FT_FLAT_COMPILE |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 20 | |
David Turner | a90663f | 2000-07-08 00:41:13 +0000 | [diff] [blame] | 21 | #include "z1gload.h" |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 22 | |
David Turner | a90663f | 2000-07-08 00:41:13 +0000 | [diff] [blame] | 23 | #else |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 24 | |
David Turner | a90663f | 2000-07-08 00:41:13 +0000 | [diff] [blame] | 25 | #include <type1z/z1gload.h> |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 26 | |
David Turner | a90663f | 2000-07-08 00:41:13 +0000 | [diff] [blame] | 27 | #endif |
| 28 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 29 | |
David Turner | efce08d | 2000-05-11 18:23:52 +0000 | [diff] [blame] | 30 | #include <freetype/internal/ftdebug.h> |
| 31 | #include <freetype/internal/ftstream.h> |
David Turner | f9ca2bb | 2000-06-30 23:12:55 +0000 | [diff] [blame] | 32 | #include <freetype/ftoutln.h> |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 33 | #include <freetype/internal/psaux.h> |
| 34 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 35 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 36 | #include <string.h> /* for strcmp() */ |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 37 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 38 | |
| 39 | /*************************************************************************/ |
| 40 | /* */ |
| 41 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
| 42 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
| 43 | /* messages during execution. */ |
| 44 | /* */ |
| 45 | #undef FT_COMPONENT |
| 46 | #define FT_COMPONENT trace_z1gload |
| 47 | |
| 48 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 49 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 50 | /*************************************************************************/ |
| 51 | /*************************************************************************/ |
| 52 | /*************************************************************************/ |
| 53 | /********** *********/ |
| 54 | /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ |
| 55 | /********** *********/ |
| 56 | /********** The following code is in charge of computing *********/ |
| 57 | /********** the maximum advance width of the font. It *********/ |
| 58 | /********** quickly processes each glyph charstring to *********/ |
| 59 | /********** extract the value from either a `sbw' or `seac' *********/ |
| 60 | /********** operator. *********/ |
| 61 | /********** *********/ |
| 62 | /*************************************************************************/ |
| 63 | /*************************************************************************/ |
| 64 | /*************************************************************************/ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 65 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 66 | |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 67 | static |
| 68 | FT_Error Z1_Parse_Glyph( T1_Decoder* decoder, |
| 69 | FT_UInt glyph_index ) |
| 70 | { |
| 71 | T1_Face face = (T1_Face)decoder->builder.face; |
| 72 | T1_Font* type1 = &face->type1; |
| 73 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame^] | 74 | return decoder->funcs.parse_charstrings( decoder, |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 75 | type1->charstrings [glyph_index], |
| 76 | type1->charstrings_len[glyph_index] ); |
| 77 | } |
| 78 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 79 | LOCAL_FUNC |
David Turner | 728da1c | 2000-06-27 23:21:51 +0000 | [diff] [blame] | 80 | FT_Error Z1_Compute_Max_Advance( T1_Face face, |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 81 | FT_Int* max_advance ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 82 | { |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 83 | FT_Error error; |
| 84 | T1_Decoder decoder; |
| 85 | FT_Int glyph_index; |
| 86 | T1_Font* type1 = &face->type1; |
| 87 | PSAux_Interface* psaux = (PSAux_Interface*)face->psaux; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 88 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 89 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 90 | *max_advance = 0; |
| 91 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 92 | /* Initialize load decoder */ |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 93 | error = psaux->t1_decoder_funcs->init( &decoder, |
| 94 | (FT_Face)face, |
| 95 | 0, /* size */ |
| 96 | 0, /* glyph slot */ |
| 97 | (FT_Byte**)type1->glyph_names, |
| 98 | face->blend, |
| 99 | Z1_Parse_Glyph ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 100 | |
David Turner | 0dd3434 | 2000-02-02 12:20:53 +0000 | [diff] [blame] | 101 | decoder.builder.metrics_only = 1; |
| 102 | decoder.builder.load_points = 0; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 103 | |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 104 | decoder.num_subrs = type1->num_subrs; |
| 105 | decoder.subrs = type1->subrs; |
| 106 | decoder.subrs_len = type1->subrs_len; |
| 107 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 108 | /* for each glyph, parse the glyph charstring and extract */ |
| 109 | /* the advance width */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 110 | for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) |
| 111 | { |
| 112 | /* now get load the unscaled outline */ |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 113 | error = Z1_Parse_Glyph( &decoder, glyph_index ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 114 | /* ignore the error if one occured - skip to next glyph */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | *max_advance = decoder.builder.advance.x; |
| 118 | return T1_Err_Ok; |
| 119 | } |
| 120 | |
| 121 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 122 | /*************************************************************************/ |
| 123 | /*************************************************************************/ |
| 124 | /*************************************************************************/ |
| 125 | /********** *********/ |
| 126 | /********** UNHINTED GLYPH LOADER *********/ |
| 127 | /********** *********/ |
| 128 | /********** The following code is in charge of loading a *********/ |
| 129 | /********** single outline. It completely ignores hinting *********/ |
| 130 | /********** and is used when FT_LOAD_NO_HINTING is set. *********/ |
| 131 | /********** *********/ |
| 132 | /********** The Type 1 hinter is located in `t1hint.c' *********/ |
| 133 | /********** *********/ |
| 134 | /*************************************************************************/ |
| 135 | /*************************************************************************/ |
| 136 | /*************************************************************************/ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 137 | |
| 138 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 139 | LOCAL_FUNC |
David Turner | 728da1c | 2000-06-27 23:21:51 +0000 | [diff] [blame] | 140 | FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph, |
| 141 | Z1_Size size, |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 142 | FT_Int glyph_index, |
| 143 | FT_Int load_flags ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 144 | { |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 145 | FT_Error error; |
| 146 | T1_Decoder decoder; |
| 147 | T1_Face face = (T1_Face)glyph->root.face; |
| 148 | FT_Bool hinting; |
| 149 | T1_Font* type1 = &face->type1; |
| 150 | PSAux_Interface* psaux = (PSAux_Interface*)face->psaux; |
| 151 | const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 152 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 153 | |
| 154 | if ( load_flags & FT_LOAD_NO_RECURSE ) |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 155 | load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; |
| 156 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 157 | glyph->x_scale = size->root.metrics.x_scale; |
| 158 | glyph->y_scale = size->root.metrics.y_scale; |
| 159 | |
| 160 | glyph->root.outline.n_points = 0; |
| 161 | glyph->root.outline.n_contours = 0; |
| 162 | |
| 163 | hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 && |
| 164 | ( load_flags & FT_LOAD_NO_HINTING ) == 0; |
| 165 | |
David Turner | 728da1c | 2000-06-27 23:21:51 +0000 | [diff] [blame] | 166 | glyph->root.format = ft_glyph_format_outline; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 167 | |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 168 | error = decoder_funcs->init( &decoder, |
| 169 | (FT_Face)face, |
| 170 | (FT_Size)size, |
| 171 | (FT_GlyphSlot)glyph, |
| 172 | (FT_Byte**)type1->glyph_names, |
| 173 | face->blend, |
| 174 | Z1_Parse_Glyph ); |
| 175 | if (error) |
| 176 | goto Exit; |
| 177 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 178 | decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0; |
| 179 | |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 180 | decoder.num_subrs = type1->num_subrs; |
| 181 | decoder.subrs = type1->subrs; |
| 182 | decoder.subrs_len = type1->subrs_len; |
| 183 | |
| 184 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 185 | /* now load the unscaled outline */ |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 186 | error = Z1_Parse_Glyph( &decoder, glyph_index ); |
| 187 | if (error) |
| 188 | goto Exit; |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 189 | |
| 190 | /* save new glyph tables */ |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 191 | decoder_funcs->done( &decoder ); |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 192 | |
| 193 | /* now, set the metrics -- this is rather simple, as */ |
| 194 | /* the left side bearing is the xMin, and the top side */ |
| 195 | /* bearing the yMax */ |
| 196 | if ( !error ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 197 | { |
David Turner | c49f69c | 2000-07-20 03:44:50 +0000 | [diff] [blame] | 198 | glyph->root.outline.flags &= ft_outline_owner; |
| 199 | glyph->root.outline.flags |= ft_outline_reverse_fill; |
| 200 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 201 | /* for composite glyphs, return only left side bearing and */ |
| 202 | /* advance width */ |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 203 | if ( load_flags & FT_LOAD_NO_RECURSE ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 204 | { |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 205 | glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; |
| 206 | glyph->root.metrics.horiAdvance = decoder.builder.advance.x; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 207 | } |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 208 | else |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 209 | { |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 210 | FT_BBox cbox; |
| 211 | FT_Glyph_Metrics* metrics = &glyph->root.metrics; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 212 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 213 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 214 | /* copy the _unscaled_ advance width */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 215 | metrics->horiAdvance = decoder.builder.advance.x; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 216 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 217 | /* make up vertical metrics */ |
| 218 | metrics->vertBearingX = 0; |
| 219 | metrics->vertBearingY = 0; |
| 220 | metrics->vertAdvance = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 221 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 222 | glyph->root.format = ft_glyph_format_outline; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 223 | |
David Turner | d8723b4 | 2000-04-14 11:29:14 +0000 | [diff] [blame] | 224 | if ( size && size->root.metrics.y_ppem < 24 ) |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 225 | glyph->root.outline.flags |= ft_outline_high_precision; |
David Turner | 82942cc | 2000-03-30 08:43:03 +0000 | [diff] [blame] | 226 | |
David Turner | 24d7024 | 2000-08-17 01:09:06 +0000 | [diff] [blame] | 227 | /* apply the font matrix */ |
| 228 | FT_Outline_Transform( &glyph->root.outline, |
| 229 | &face->type1.font_matrix ); |
| 230 | |
| 231 | FT_Outline_Translate( &glyph->root.outline, |
| 232 | face->type1.font_offset.x, |
| 233 | face->type1.font_offset.y ); |
| 234 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 235 | #if 0 |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 236 | glyph->root.outline.second_pass = TRUE; |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 237 | glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24; |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 238 | glyph->root.outline.dropout_mode = 2; |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 239 | #endif /* 0 */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 240 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 241 | if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 242 | { |
| 243 | /* scale the outline and the metrics */ |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 244 | FT_Int n; |
David Turner | f0df85b | 2000-06-22 00:17:42 +0000 | [diff] [blame] | 245 | FT_Outline* cur = decoder.builder.base; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 246 | FT_Vector* vec = cur->points; |
| 247 | FT_Fixed x_scale = glyph->x_scale; |
| 248 | FT_Fixed y_scale = glyph->y_scale; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 249 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 250 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 251 | /* First of all, scale the points */ |
| 252 | for ( n = cur->n_points; n > 0; n--, vec++ ) |
| 253 | { |
| 254 | vec->x = FT_MulFix( vec->x, x_scale ); |
| 255 | vec->y = FT_MulFix( vec->y, y_scale ); |
| 256 | } |
David Turner | d8723b4 | 2000-04-14 11:29:14 +0000 | [diff] [blame] | 257 | |
| 258 | FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 259 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 260 | /* Then scale the metrics */ |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 261 | metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); |
Werner Lemberg | ac39ecd | 2000-06-30 22:24:36 +0000 | [diff] [blame] | 262 | metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 263 | |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 264 | metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); |
| 265 | metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); |
David Turner | ed7f62a | 2000-03-28 11:19:28 +0000 | [diff] [blame] | 266 | } |
David Turner | d8723b4 | 2000-04-14 11:29:14 +0000 | [diff] [blame] | 267 | |
| 268 | /* compute the other metrics */ |
| 269 | FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 270 | |
David Turner | d8723b4 | 2000-04-14 11:29:14 +0000 | [diff] [blame] | 271 | /* grid fit the bounding box if necessary */ |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 272 | if ( hinting ) |
David Turner | d8723b4 | 2000-04-14 11:29:14 +0000 | [diff] [blame] | 273 | { |
| 274 | cbox.xMin &= -64; |
| 275 | cbox.yMin &= -64; |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 276 | cbox.xMax = ( cbox.xMax+63 ) & -64; |
| 277 | cbox.yMax = ( cbox.yMax+63 ) & -64; |
David Turner | d8723b4 | 2000-04-14 11:29:14 +0000 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | metrics->width = cbox.xMax - cbox.xMin; |
| 281 | metrics->height = cbox.yMax - cbox.yMin; |
| 282 | |
| 283 | metrics->horiBearingX = cbox.xMin; |
| 284 | metrics->horiBearingY = cbox.yMax; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 285 | } |
| 286 | } |
David Turner | 9748807 | 2000-08-22 22:36:33 +0000 | [diff] [blame] | 287 | Exit: |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 288 | return error; |
| 289 | } |
| 290 | |
Werner Lemberg | 7fa51b5 | 2000-07-08 19:51:42 +0000 | [diff] [blame] | 291 | |
| 292 | /* END */ |