1 /* -*- coding: utf-8 -*- */
2 /* Copyright (C) 2000-2012 by George Williams */
3 /*
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13
14 * The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <fontforge-config.h>
30
31 #include "autotrace.h"
32 #include "charset.h"
33 #include "encoding.h"
34 #include "ffglib.h"
35 #include "fontforgeui.h"
36 #include "gfile.h"
37 #include "gkeysym.h"
38 #include "gresedit.h"
39 #include "gresource.h"
40 #include "groups.h"
41 #include "macenc.h"
42 #include "namelist.h"
43 #include "othersubrs.h"
44 #include "prefs.h"
45 #include "sfd.h"
46 #include "splineutil.h"
47 #include "ttf.h"
48 #include "ustring.h"
49
50 #include <dirent.h>
51 #include <locale.h>
52 #include <stdlib.h>
53 #include <sys/time.h>
54 #include <sys/types.h>
55 #include <time.h>
56
57 #if HAVE_LANGINFO_H
58 # include <langinfo.h>
59 #endif
60
61 #define RAD2DEG (180/FF_PI)
62
63 static void change_res_filename(const char *newname);
64
65 extern int splash;
66 extern int adjustwidth;
67 extern int adjustlbearing;
68 extern Encoding *default_encoding;
69 extern int autohint_before_generate;
70 extern int use_freetype_to_rasterize_fv;
71 extern int use_freetype_with_aa_fill_cv;
72 extern int OpenCharsInNewWindow;
73 extern int ItalicConstrained;
74 extern int accent_offset;
75 extern int GraveAcuteCenterBottom;
76 extern int PreferSpacingAccents;
77 extern int CharCenterHighest;
78 extern int ask_user_for_resolution;
79 #ifndef _NO_LIBPNG
80 extern int WritePNGInSFD;
81 #endif
82 extern int stop_at_join;
83 extern int recognizePUA;
84 extern float arrowAmount;
85 extern float arrowAccelFactor;
86 extern float snapdistance;
87 extern float snapdistancemeasuretool;
88 extern int measuretoolshowhorizontolvertical;
89 extern int snaptoint;
90 extern float joinsnap;
91 extern char *BDFFoundry;
92 extern char *TTFFoundry;
93 extern char *xuid;
94 extern char *SaveTablesPref;
95 /*struct cvshows CVShows = { 1, 1, 1, 1, 1, 0, 1 };*/ /* in charview */
96 /* int default_fv_font_size = 24; */ /* in fontview */
97 /* int default_fv_antialias = false */ /* in fontview */
98 /* int default_fv_bbsized = false */ /* in fontview */
99 extern int default_fv_row_count; /* in fontview */
100 extern int default_fv_col_count; /* in fontview */
101 extern int default_fv_showhmetrics; /* in fontview */
102 extern int default_fv_showvmetrics; /* in fontview */
103 extern int default_fv_glyphlabel; /* in fontview */
104 extern int save_to_dir; /* in fontview, use sfdir rather than sfd */
105 extern int palettes_docked; /* in cvpalettes */
106 extern int cvvisible[2], bvvisible[3]; /* in cvpalettes.c */
107 extern int maxundoes; /* in cvundoes */
108 extern int pref_mv_shift_and_arrow_skip; /* in metricsview.c */
109 extern int pref_mv_control_shift_and_arrow_skip; /* in metricsview.c */
110 extern int mv_type; /* in metricsview.c */
111 extern int prefer_cjk_encodings; /* in parsettf */
112 extern int onlycopydisplayed, copymetadata, copyttfinstr;
113 extern struct cvshows CVShows;
114 extern int infowindowdistance; /* in cvruler.c */
115 extern int oldformatstate; /* in savefontdlg.c */
116 extern int oldbitmapstate; /* in savefontdlg.c */
117 static int old_ttf_flags=0, old_otf_flags=0;
118 extern int old_sfnt_flags; /* in savefont.c */
119 extern int old_ps_flags; /* in savefont.c */
120 extern int old_validate; /* in savefontdlg.c */
121 extern int old_fontlog; /* in savefontdlg.c */
122 extern int oldsystem; /* in bitmapdlg.c */
123 extern int preferpotrace; /* in autotrace.c */
124 extern int autotrace_ask; /* in autotrace.c */
125 extern int mf_ask; /* in autotrace.c */
126 extern int mf_clearbackgrounds; /* in autotrace.c */
127 extern int mf_showerrors; /* in autotrace.c */
128 extern char *mf_args; /* in autotrace.c */
129 static int glyph_2_name_map=0; /* was in tottf.c, now a flag in savefont options dlg */
130 extern int coverageformatsallowed; /* in tottfgpos.c */
131 extern int debug_wins; /* in cvdebug.c */
132 extern int gridfit_dpi, gridfit_depth; /* in cvgridfit.c */
133 extern float gridfit_pointsizey; /* in cvgridfit.c */
134 extern float gridfit_pointsizex; /* in cvgridfit.c */
135 extern int gridfit_x_sameas_y; /* in cvgridfit.c */
136 extern int hint_diagonal_ends; /* in stemdb.c */
137 extern int hint_diagonal_intersections; /* in stemdb.c */
138 extern int hint_bounding_boxes; /* in stemdb.c */
139 extern int detect_diagonal_stems; /* in stemdb.c */
140 extern float stem_slope_error; /* in stemdb.c */
141 extern float stub_slope_error; /* in stemdb.c */
142 extern int instruct_diagonal_stems; /* in nowakowskittfinstr.c */
143 extern int instruct_serif_stems; /* in nowakowskittfinstr.c */
144 extern int instruct_ball_terminals; /* in nowakowskittfinstr.c */
145 extern int interpolate_strong; /* in nowakowskittfinstr.c */
146 extern int control_counters; /* in nowakowskittfinstr.c */
147 extern unichar_t *script_menu_names[SCRIPT_MENU_MAX];
148 extern char *script_filenames[SCRIPT_MENU_MAX];
149 static char *xdefs_filename;
150 extern int new_em_size; /* in splineutil2.c */
151 extern int new_fonts_are_order2; /* in splineutil2.c */
152 extern int loaded_fonts_same_as_new; /* in splineutil2.c */
153 extern int use_second_indic_scripts; /* in tottfgpos.c */
154 static char *othersubrsfile = NULL;
155 extern MacFeat *default_mac_feature_map, /* from macenc.c */
156 *user_mac_feature_map;
157 extern int updateflex; /* in charview.c */
158 extern int default_autokern_dlg; /* in lookupui.c */
159 extern int allow_utf8_glyphnames; /* in lookupui.c */
160 extern int add_char_to_name_list; /* in charinfo.c */
161 extern int clear_tt_instructions_when_needed; /* in cvundoes.c */
162 extern int export_clipboard; /* in cvundoes.c */
163 extern int cv_width; /* in charview.c */
164 extern int cv_height; /* in charview.c */
165 extern int cv_show_fill_with_space; /* in charview.c */
166 extern int interpCPsOnMotion; /* in charview.c */
167 extern int DrawOpenPathsWithHighlight; /* in charview.c */
168 extern float prefs_cvEditHandleSize; /* in charview.c */
169 extern int prefs_cvInactiveHandleAlpha; /* in charview.c */
170 extern int mv_width; /* in metricsview.c */
171 extern int mv_height; /* in metricsview.c */
172 extern int fvmv_selectmax; /* in metricsview.c */
173 extern int bv_width; /* in bitmapview.c */
174 extern int bv_height; /* in bitmapview.c */
175 extern int ask_user_for_cmap; /* in parsettf.c */
176 extern int mvshowgrid; /* in metricsview.c */
177
178 extern int rectelipse, polystar, regular_star; /* from cvpalettes.c */
179 extern int center_out[2]; /* from cvpalettes.c */
180 extern float rr_radius; /* from cvpalettes.c */
181 extern int ps_pointcnt; /* from cvpalettes.c */
182 extern float star_percent; /* from cvpalettes.c */
183 extern int home_char; /* from fontview.c */
184 extern int compact_font_on_open; /* from fontview.c */
185 extern int aa_pixelsize; /* from anchorsaway.c */
186 extern enum cvtools cv_b1_tool, cv_cb1_tool, cv_b2_tool, cv_cb2_tool; /* cvpalettes.c */
187 extern int show_kerning_pane_in_class; /* kernclass.c */
188 extern int AutoSaveFrequency; /* autosave.c */
189 extern int UndoRedoLimitToSave; /* sfd.c */
190 extern int UndoRedoLimitToLoad; /* sfd.c */
191 extern int prefRevisionsToRetain; /* sfd.c */
192 extern int prefs_cv_show_control_points_always_initially; /* from charview.c */
193 extern int prefs_create_dragging_comparison_outline; /* from charview.c */
194 extern int prefs_cv_outline_thickness; /* from charview.c */
195
196 extern float OpenTypeLoadHintEqualityTolerance; /* autohint.c */
197 extern float GenerateHintWidthEqualityTolerance; /* splinesave.c */
198 extern int warn_script_unsaved; /* fontview.c */
199 extern NameList *force_names_when_opening;
200 extern NameList *force_names_when_saving;
201 extern NameList *namelist_for_new_fonts;
202
203 extern int default_font_filter_index;
204 extern struct openfilefilters *user_font_filters;
205 static int alwaysgenapple=false, alwaysgenopentype=false;
206
207 static int gfc_showhidden, gfc_dirplace;
208 static char *gfc_bookmarks=NULL;
209
210 static int prefs_usecairo = true;
211
212 static int pointless;
213
214 /* These first three must match the values in macenc.c */
215 #define CID_Features 101
216 #define CID_FeatureDel 103
217 #define CID_FeatureEdit 105
218
219 #define CID_Mapping 102
220 #define CID_MappingDel 104
221 #define CID_MappingEdit 106
222
223 #define CID_ScriptMNameBase 200
224 #define CID_ScriptMFileBase (200+SCRIPT_MENU_MAX)
225 #define CID_ScriptMBrowseBase (200+2*SCRIPT_MENU_MAX)
226
227 #define CID_PrefsBase 1000
228 #define CID_PrefsOffset 100
229 #define CID_PrefsBrowseOffset (CID_PrefsOffset/2)
230
231 //////////////////////////////////
232 // The _oldval_ are used to cache the setting when the prefs window
233 // is created so that a redraw can be performed only when the
234 // value has changed.
235 float prefs_oldval_cvEditHandleSize = 0;
236 int prefs_oldval_cvInactiveHandleAlpha = 0;
237
238 /* ************************************************************************** */
239 /* ***************************** mac data ***************************** */
240 /* ************************************************************************** */
241
242 extern struct macsettingname macfeat_otftag[], *user_macfeat_otftag;
243
UserSettingsFree(void)244 static void UserSettingsFree(void) {
245
246 free( user_macfeat_otftag );
247 user_macfeat_otftag = NULL;
248 }
249
UserSettingsDiffer(void)250 static int UserSettingsDiffer(void) {
251 int i,j;
252
253 if ( user_macfeat_otftag==NULL )
254 return( false );
255
256 for ( i=0; user_macfeat_otftag[i].otf_tag!=0; ++i );
257 for ( j=0; macfeat_otftag[j].otf_tag!=0; ++j );
258 if ( i!=j )
259 return( true );
260 for ( i=0; user_macfeat_otftag[i].otf_tag!=0; ++i ) {
261 for ( j=0; macfeat_otftag[j].otf_tag!=0; ++j ) {
262 if ( macfeat_otftag[j].mac_feature_type ==
263 user_macfeat_otftag[i].mac_feature_type &&
264 macfeat_otftag[j].mac_feature_setting ==
265 user_macfeat_otftag[i].mac_feature_setting &&
266 macfeat_otftag[j].otf_tag ==
267 user_macfeat_otftag[i].otf_tag )
268 break;
269 }
270 if ( macfeat_otftag[j].otf_tag==0 )
271 return( true );
272 }
273 return( false );
274 }
275
276 /**************************************************************************** */
277
278
279 /* don't use mnemonics 'C' or 'O' (Cancel & OK) */
280 enum pref_types { pr_int, pr_real, pr_bool, pr_enum, pr_encoding, pr_string,
281 pr_file, pr_namelist, pr_unicode, pr_angle };
282 struct enums { char *name; int value; };
283
284 struct enums fvsize_enums[] = { {NULL, 0} };
285
286 #define PREFS_LIST_EMPTY { NULL, 0, NULL, NULL, NULL, '\0', NULL, 0, NULL }
287 static struct prefs_list {
288 char *name;
289 /* In the prefs file the untranslated name will always be used, but */
290 /* in the UI that name may be translated. */
291 enum pref_types type;
292 void *val;
293 void *(*get)(void);
294 void (*set)(void *);
295 char mn;
296 struct enums *enums;
297 unsigned int dontdisplay: 1;
298 char *popup;
299 } general_list[] = {
300 /* GT: The following strings have no spaces and an odd capitalization */
301 /* GT: this is because these strings are used in two different ways, one */
302 /* GT: translated (which the user sees, and should probably have added spaces,*/
303 /* GT: and one untranslated which needs the current odd format */
304 { N_("ResourceFile"), pr_file, &xdefs_filename, NULL, NULL, 'R', NULL, 0, N_("When FontForge starts up, it loads the user interface theme from\nthis file. Any changes will only take effect the next time you start FontForge.") },
305 { N_("OtherSubrsFile"), pr_file, &othersubrsfile, NULL, NULL, 'O', NULL, 0, N_("If you wish to replace Adobe's OtherSubrs array (for Type1 fonts)\nwith an array of your own, set this to point to a file containing\na list of up to 14 PostScript subroutines. Each subroutine must\nbe preceded by a line starting with '%%%%' (any text before the\nfirst '%%%%' line will be treated as an initial copyright notice).\nThe first three subroutines are for flex hints, the next for hint\nsubstitution (this MUST be present), the 14th (or 13 as the\nnumbering actually starts with 0) is for counter hints.\nThe subroutines should not be enclosed in a [ ] pair.") },
306 { N_("FreeTypeInFontView"), pr_bool, &use_freetype_to_rasterize_fv, NULL, NULL, 'O', NULL, 0, N_("Use the FreeType rasterizer (when available)\nto rasterize glyphs in the font view.\nThis generally results in better quality.") },
307 { N_("FreeTypeAAFillInOutlineView"), pr_bool, &use_freetype_with_aa_fill_cv, NULL, NULL, 'O', NULL, 0, N_("When filling using freetype in the outline view,\nhave freetype render the glyph antialiased.") },
308 { N_("SplashScreen"), pr_bool, &splash, NULL, NULL, 'S', NULL, 0, N_("Show splash screen on start-up") },
309 #ifndef _NO_LIBCAIRO
310 { N_("UseCairoDrawing"), pr_bool, &prefs_usecairo, NULL, NULL, '\0', NULL, 0, N_("Use the cairo library for drawing (if available)\nThis makes for prettier (anti-aliased) but slower drawing\nThis applies to any windows created AFTER this is set.\nAlready existing windows will continue as they are.") },
311 #endif
312 { N_("ExportClipboard"), pr_bool, &export_clipboard, NULL, NULL, '\0', NULL, 0, N_( "If you are running an X11 clipboard manager you might want\nto turn this off. FF can put things into its internal clipboard\nwhich it cannot export to X11 (things like copying more than\none glyph in the fontview). If you have a clipboard manager\nrunning it will force these to be exported with consequent\nloss of data.") },
313 { N_("AutoSaveFrequency"), pr_int, &AutoSaveFrequency, NULL, NULL, '\0', NULL, 0, N_( "The number of seconds between autosaves. If you set this to 0 there will be no autosaves.") },
314 { N_("RevisionsToRetain"), pr_int, &prefRevisionsToRetain, NULL, NULL, '\0', NULL, 0, N_( "When Saving, keep this number of previous versions of the file. file.sfd-01 will be the last saved file, file.sfd-02 will be the file saved before that, and so on. If you set this to 0 then no revisions will be retained.") },
315 { N_("UndoRedoLimitToSave"), pr_int, &UndoRedoLimitToSave, NULL, NULL, '\0', NULL, 0, N_( "The number of undo and redo operations which will be saved in sfd files.\nIf you set this to 0 undo/redo information is not saved to sfd files.\nIf set to -1 then all available undo/redo information is saved without limit.") },
316 { N_("WarnScriptUnsaved"), pr_bool, &warn_script_unsaved, NULL, NULL, '\0', NULL, 0, N_( "Whether or not to warn you if you have an unsaved script in the «Execute Script» dialog.") },
317 PREFS_LIST_EMPTY
318 },
319 new_list[] = {
320 { N_("NewCharset"), pr_encoding, &default_encoding, NULL, NULL, 'N', NULL, 0, N_("Default encoding for\nnew fonts") },
321 { N_("NewEmSize"), pr_int, &new_em_size, NULL, NULL, 'S', NULL, 0, N_("The default size of the Em-Square in a newly created font.") },
322 { N_("NewFontsQuadratic"), pr_bool, &new_fonts_are_order2, NULL, NULL, 'Q', NULL, 0, N_("Whether new fonts should contain splines of quadratic (truetype)\nor cubic (postscript & opentype).") },
323 { N_("LoadedFontsAsNew"), pr_bool, &loaded_fonts_same_as_new, NULL, NULL, 'L', NULL, 0, N_("Whether fonts loaded from the disk should retain their splines\nwith the original order (quadratic or cubic), or whether the\nsplines should be converted to the default order for new fonts\n(see NewFontsQuadratic).") },
324 PREFS_LIST_EMPTY
325 },
326 open_list[] = {
327 { N_("PreferCJKEncodings"), pr_bool, &prefer_cjk_encodings, NULL, NULL, 'C', NULL, 0, N_("When loading a truetype or opentype font which has both a unicode\nand a CJK encoding table, use this flag to specify which\nshould be loaded for the font.") },
328 { N_("AskUserForCMap"), pr_bool, &ask_user_for_cmap, NULL, NULL, 'O', NULL, 0, N_("When loading a font in sfnt format (TrueType, OpenType, etc.),\nask the user to specify which cmap to use initially.") },
329 { N_("PreserveTables"), pr_string, &SaveTablesPref, NULL, NULL, 'P', NULL, 0, N_("Enter a list of 4 letter table tags, separated by commas.\nFontForge will make a binary copy of these tables when it\nloads a True/OpenType font, and will output them (unchanged)\nwhen it generates the font. Do not include table tags which\nFontForge thinks it understands.") },
330 { N_("SeekCharacter"), pr_unicode, &home_char, NULL, NULL, '\0', NULL, 0, N_("When fontforge opens a (non-sfd) font it will try to display this unicode character in the fontview.")},
331 { N_("CompactOnOpen"), pr_bool, &compact_font_on_open, NULL, NULL, 'O', NULL, 0, N_("When a font is opened, should it be made compact?")},
332 { N_("UndoRedoLimitToLoad"), pr_int, &UndoRedoLimitToLoad, NULL, NULL, '\0', NULL, 0, N_( "The number of undo and redo operations to load from sfd files.\nWith this option you can disregard undo information while loading SFD files.\nIf set to 0 then no undo/redo information is loaded.\nIf set to -1 then all available undo/redo information is loaded without limit.") },
333 { N_("OpenTypeLoadHintEqualityTolerance"), pr_real, &OpenTypeLoadHintEqualityTolerance, NULL, NULL, '\0', NULL, 0, N_( "When importing an OpenType font, for the purposes of hinting spline points might not exactly match boundaries. For example, a point might be -0.0002 instead of exactly 0\nThis setting gives the user some control over this allowing a small tolerance value to be fed into the OpenType loading code.\nComparisons are then not performed for raw equality but for equality within tolerance (e.g., values within the range -0.0002 to 0.0002 will be considered equal to 0 when figuring out hints).") },
334 PREFS_LIST_EMPTY
335 },
336 navigation_list[] = {
337 { N_("GlyphAutoGoto"), pr_bool, &cv_auto_goto, NULL, NULL, '\0', NULL, 0, N_("Typing a normal character in the glyph view window changes the window to look at that character.\nEnabling GlyphAutoGoto will disable the shortcut where holding just the ` key will enable Preview mode as long as the key is held.") },
338 { N_("OpenCharsInNewWindow"), pr_bool, &OpenCharsInNewWindow, NULL, NULL, '\0', NULL, 0, N_("When double clicking on a character in the font view\nopen that character in a new window, otherwise\nreuse an existing one.") },
339 { N_("FontViewMetricsViewSelectMax"), pr_int, &fvmv_selectmax, NULL, NULL, '\0', NULL, 0, N_("When characters are selected in the FontView, how many should be put into the MetricsView if you open one? Negative values mean there's no limit, which should be used sparingly.") },
340 PREFS_LIST_EMPTY
341 },
342 editing_list[] = {
343 { N_("ItalicConstrained"), pr_bool, &ItalicConstrained, NULL, NULL, '\0', NULL, 0, N_("In the Outline View, the Shift key constrains motion to be parallel to the ItalicAngle rather than constraining it to be vertical.") },
344 { N_("InterpolateCPsOnMotion"), pr_bool, &interpCPsOnMotion, NULL, NULL, '\0', NULL, 0, N_("When moving one end point of a spline but not the other\ninterpolate the control points between the two.") },
345 { N_("SnapDistance"), pr_real, &snapdistance, NULL, NULL, '\0', NULL, 0, N_("When the mouse pointer is within this many pixels\nof one of the various interesting features (baseline,\nwidth, grid splines, etc.) the pointer will snap\nto that feature.") },
346 { N_("SnapDistanceMeasureTool"), pr_real, &snapdistancemeasuretool, NULL, NULL, '\0', NULL, 0, N_("When the measure tool is active and when the mouse pointer is within this many pixels\nof one of the various interesting features (baseline,\nwidth, grid splines, etc.) the pointer will snap\nto that feature.") },
347 { N_("SnapToInt"), pr_bool, &snaptoint, NULL, NULL, '\0', NULL, 0, N_("When the user clicks in the editing window, round the location to the nearest integers.") },
348 { N_("StopAtJoin"), pr_bool, &stop_at_join, NULL, NULL, '\0', NULL, 0, N_("When dragging points in the outline view a join may occur\n(two open contours may connect at their endpoints). When\nthis is On a join will cause FontForge to stop moving the\nselection (as if the user had released the mouse button).\nThis is handy if your fingers are inclined to wiggle a bit.") },
349 { N_("JoinSnap"), pr_real, &joinsnap, NULL, NULL, '\0', NULL, 0, N_("The Edit->Join command will join points which are this close together\nA value of 0 means they must be coincident") },
350 { N_("CopyMetaData"), pr_bool, ©metadata, NULL, NULL, '\0', NULL, 0, N_("When copying glyphs from the font view, also copy the\nglyphs' metadata (name, encoding, comment, etc).") },
351 { N_("UndoDepth"), pr_int, &maxundoes, NULL, NULL, '\0', NULL, 0, N_("The maximum number of Undoes/Redoes stored in a glyph. Use -1 for infinite Undoes\n(but watch RAM consumption and use the Edit menu's Remove Undoes as needed)") },
352 { N_("UpdateFlex"), pr_bool, &updateflex, NULL, NULL, '\0', NULL, 0, N_("Figure out flex hints after every change") },
353 { N_("AutoKernDialog"), pr_bool, &default_autokern_dlg, NULL, NULL, '\0', NULL, 0, N_("Open AutoKern dialog for new kerning subtables") },
354 { N_("MetricsShiftSkip"), pr_int, &pref_mv_shift_and_arrow_skip, NULL, NULL, '\0', NULL, 0, N_("Number of units to increment/decrement a table value by in the metrics window when shift is held") },
355 { N_("MetricsControlShiftSkip"), pr_int, &pref_mv_control_shift_and_arrow_skip, NULL, NULL, '\0', NULL, 0, N_("Number of units to increment/decrement a table value by in the metrics window when both control and shift is held") },
356 PREFS_LIST_EMPTY
357 },
358 editing_interface_list[] = {
359 { N_("ArrowMoveSize"), pr_real, &arrowAmount, NULL, NULL, '\0', NULL, 0, N_("The number of em-units by which an arrow key will move a selected point") },
360 { N_("ArrowAccelFactor"), pr_real, &arrowAccelFactor, NULL, NULL, '\0', NULL, 0, N_("Holding down the Shift key will speed up arrow key motion by this factor") },
361 { N_("DrawOpenPathsWithHighlight"), pr_bool, &DrawOpenPathsWithHighlight, NULL, NULL, '\0', NULL, 0, N_("Open paths should be drawn in a special highlight color to make them more apparent.") },
362 { N_("MeasureToolShowHorizontalVertical"), pr_bool, &measuretoolshowhorizontolvertical, NULL, NULL, '\0', NULL, 0, N_("Have the measure tool show horizontal and vertical distances on the canvas.") },
363 { N_("EditHandleSize"), pr_real, &prefs_cvEditHandleSize, NULL, NULL, '\0', NULL, 0, N_("The size of the handles showing control points and other interesting points in the glyph editor (default is 5).") },
364 { N_("InactiveHandleAlpha"), pr_int, &prefs_cvInactiveHandleAlpha, NULL, NULL, '\0', NULL, 0, N_("Inactive handles in the glyph editor will be drawn with this alpha value (range: 0-255 default is 255).") },
365 { N_("ShowControlPointsAlways"), pr_bool, &prefs_cv_show_control_points_always_initially, NULL, NULL, '\0', NULL, 0, N_("Always show the control points when editing a glyph.\nThis can be turned off in the menu View/Show, this setting will effect if control points are shown initially.\nChange requires a restart of fontforge.") },
366 { N_("ShowFillWithSpace"), pr_bool, &cv_show_fill_with_space, NULL, NULL, '\0', NULL, 0, N_("Also enable preview mode when the space bar is pressed.") },
367 { N_("OutlineThickness"), pr_int, &prefs_cv_outline_thickness, NULL, NULL, '\0', NULL, 0, N_("Setting above 1 will cause a thick outline to be drawn for glyph paths\n which is only extended inwards from the edge of the glyph.\n See also the ForegroundThickOutlineColor Resource for the color of this outline.") },
368 PREFS_LIST_EMPTY
369 },
370 sync_list[] = {
371 { N_("AutoWidthSync"), pr_bool, &adjustwidth, NULL, NULL, '\0', NULL, 0, N_("Changing the width of a glyph\nchanges the widths of all accented\nglyphs based on it.") },
372 { N_("AutoLBearingSync"), pr_bool, &adjustlbearing, NULL, NULL, '\0', NULL, 0, N_("Changing the left side bearing\nof a glyph adjusts the lbearing\nof other references in all accented\nglyphs based on it.") },
373 PREFS_LIST_EMPTY
374 },
375 tt_list[] = {
376 { N_("ClearInstrsBigChanges"), pr_bool, &clear_tt_instructions_when_needed, NULL, NULL, 'C', NULL, 0, N_("Instructions in a TrueType font refer to\npoints by number, so if you edit a glyph\nin such a way that some points have different\nnumbers (add points, remove them, etc.) then\nthe instructions will be applied to the wrong\npoints with disasterous results.\n Normally FontForge will remove the instructions\nif it detects that the points have been renumbered\nin order to avoid the above problem. You may turn\nthis behavior off -- but be careful!") },
377 { N_("CopyTTFInstrs"), pr_bool, ©ttfinstr, NULL, NULL, '\0', NULL, 0, N_("When copying glyphs from the font view, also copy the\nglyphs' truetype instructions.") },
378 PREFS_LIST_EMPTY
379 },
380 accent_list[] = {
381 { N_("AccentOffsetPercent"), pr_int, &accent_offset, NULL, NULL, '\0', NULL, 0, N_("The percentage of an em by which an accent is offset from its base glyph in Build Accent") },
382 { N_("AccentCenterLowest"), pr_bool, &GraveAcuteCenterBottom, NULL, NULL, '\0', NULL, 0, N_("When placing grave and acute accents above letters, should\nFontForge center them based on their full width, or\nshould it just center based on the lowest point\nof the accent.") },
383 { N_("CharCenterHighest"), pr_bool, &CharCenterHighest, NULL, NULL, '\0', NULL, 0, N_("When centering an accent over a glyph, should the accent\nbe centered on the highest point(s) of the glyph,\nor the middle of the glyph?") },
384 { N_("PreferSpacingAccents"), pr_bool, &PreferSpacingAccents, NULL, NULL, '\0', NULL, 0, N_("Use spacing accents (Unicode: 02C0-02FF) rather than\ncombining accents (Unicode: 0300-036F) when\nbuilding accented glyphs.") },
385 PREFS_LIST_EMPTY
386 },
387 args_list[] = {
388 { N_("PreferPotrace"), pr_bool, &preferpotrace, NULL, NULL, '\0', NULL, 0, N_("FontForge supports two different helper applications to do autotracing\n autotrace and potrace\nIf your system only has one it will use that one, if you have both\nuse this option to tell FontForge which to pick.") },
389 { N_("AutotraceArgs"), pr_string, NULL, GetAutoTraceArgs, SetAutoTraceArgs, '\0', NULL, 0, N_("Extra arguments for configuring the autotrace program\n(either autotrace or potrace)") },
390 { N_("AutotraceAsk"), pr_bool, &autotrace_ask, NULL, NULL, '\0', NULL, 0, N_("Ask the user for autotrace arguments each time autotrace is invoked") },
391 { N_("MfArgs"), pr_string, &mf_args, NULL, NULL, '\0', NULL, 0, N_("Commands to pass to mf (metafont) program, the filename will follow these") },
392 { N_("MfAsk"), pr_bool, &mf_ask, NULL, NULL, '\0', NULL, 0, N_("Ask the user for mf commands each time mf is invoked") },
393 { N_("MfClearBg"), pr_bool, &mf_clearbackgrounds, NULL, NULL, '\0', NULL, 0, N_("FontForge loads large images into the background of each glyph\nprior to autotracing them. You may retain those\nimages to look at after mf processing is complete, or\nremove them to save space") },
394 { N_("MfShowErr"), pr_bool, &mf_showerrors, NULL, NULL, '\0', NULL, 0, N_("MetaFont (mf) generates lots of verbiage to stdout.\nMost of the time I find it an annoyance but it is\nimportant to see if something goes wrong.") },
395 PREFS_LIST_EMPTY
396 },
397 fontinfo_list[] = {
398 { N_("FoundryName"), pr_string, &BDFFoundry, NULL, NULL, 'F', NULL, 0, N_("Name used for foundry field in bdf\nfont generation") },
399 { N_("TTFFoundry"), pr_string, &TTFFoundry, NULL, NULL, 'T', NULL, 0, N_("Name used for Vendor ID field in\nttf (OS/2 table) font generation.\nMust be no more than 4 characters") },
400 { N_("NewFontNameList"), pr_namelist, &namelist_for_new_fonts, NULL, NULL, '\0', NULL, 0, N_("FontForge will use this namelist when assigning\nglyph names to code points in a new font.") },
401 { N_("RecognizePUANames"), pr_bool, &recognizePUA, NULL, NULL, 'U', NULL, 0, N_("Once upon a time, Adobe assigned PUA (public use area) encodings\nfor many stylistic variants of characters (small caps, old style\nnumerals, etc.). Adobe no longer believes this to be a good idea,\nand recommends that these encodings be ignored.\n\n The assignments were originally made because most applications\ncould not handle OpenType features for accessing variants. Adobe\nnow believes that all apps that matter can now do so. Applications\nlike Word and OpenOffice still can't handle these features, so\n fontforge's default behavior is to ignore Adobe's current\nrecommendations.\n\nNote: This does not affect figuring out unicode from the font's encoding,\nit just controls determining unicode from a name.") },
402 { N_("UnicodeGlyphNames"), pr_bool, &allow_utf8_glyphnames, NULL, NULL, 'O', NULL, 0, N_("Allow the full unicode character set in glyph names.\nThis does not conform to adobe's glyph name standard.\nSuch names should be for internal use only and\nshould NOT end up in production fonts." ) },
403 { N_("AddCharToNameList"), pr_bool, &add_char_to_name_list, NULL, NULL, 'O', NULL, 0, N_( "When displaying a list of glyph names\n(or sometimes just a single glyph name)\nFontForge will add the unicode character\nthe name refers to in parenthesis after\nthe name. It does this because some names\nare obscure.\nSome people would prefer not to see this,\nso this preference item lets you turn off\n this behavior" ) },
404 PREFS_LIST_EMPTY
405 },
406 generate_list[] = {
407 { N_("AskBDFResolution"), pr_bool, &ask_user_for_resolution, NULL, NULL, 'B', NULL, 0, N_("When generating a set of BDF fonts ask the user\nto specify the screen resolution of the fonts\notherwise FontForge will guess depending on the pixel size.") },
408 { N_("AutoHint"), pr_bool, &autohint_before_generate, NULL, NULL, 'H', NULL, 0, N_("AutoHint changed glyphs before generating a font") },
409 #ifndef _NO_LIBPNG
410 { N_("WritePNGInSFD"), pr_bool, &WritePNGInSFD, NULL, NULL, 'B', NULL, 0, N_("If your SFD contains images, write them as PNG; this results in smaller SFDs; but was not supported in FontForge versions compiled before July 2019, so older FontForge versions cannot read them.") },
411 #endif
412
413 { N_("GenerateHintWidthEqualityTolerance"), pr_real, &GenerateHintWidthEqualityTolerance, NULL, NULL, '\0', NULL, 0, N_( "When generating a font, ignore slight rounding errors for hints that should be at the top or bottom of the glyph. For example, you might like to set this to 0.02 so that 19.999 will be considered 20. But only for the hint width value.") },
414
415 PREFS_LIST_EMPTY
416 },
417 hints_list[] = {
418 { N_("StandardSlopeError"), pr_angle, &stem_slope_error, NULL, NULL, '\0', NULL, 0, N_("The maximum slope difference which still allows to consider two points \"parallel\".\nEnlarge this to make the autohinter more tolerable to small deviations from straight lines when detecting stem edges.") },
419 { N_("SerifSlopeError"), pr_angle, &stub_slope_error, NULL, NULL, '\0', NULL, 0, N_("Same as above, but for terminals of small features (e. g. serifs), which can deviate more significantly from the horizontal or vertical direction.") },
420 { N_("HintBoundingBoxes"), pr_bool, &hint_bounding_boxes, NULL, NULL, '\0', NULL, 0, N_("FontForge will place vertical or horizontal hints to describe the bounding boxes of suitable glyphs.") },
421 { N_("HintDiagonalEnds"), pr_bool, &hint_diagonal_ends, NULL, NULL, '\0', NULL, 0, N_("FontForge will place vertical or horizontal hints at the ends of diagonal stems.") },
422 { N_("HintDiagonalInter"), pr_bool, &hint_diagonal_intersections, NULL, NULL, '\0', NULL, 0, N_("FontForge will place vertical or horizontal hints at the intersections of diagonal stems.") },
423 { N_("DetectDiagonalStems"), pr_bool, &detect_diagonal_stems, NULL, NULL, '\0', NULL, 0, N_("FontForge will generate diagonal stem hints, which then can be used by the AutoInstr command.") },
424 PREFS_LIST_EMPTY
425 },
426 instrs_list[] = {
427 { N_("InstructDiagonalStems"), pr_bool, &instruct_diagonal_stems, NULL, NULL, '\0', NULL, 0, N_("Generate instructions for diagonal stem hints.") },
428 { N_("InstructSerifs"), pr_bool, &instruct_serif_stems, NULL, NULL, '\0', NULL, 0, N_("Try to detect serifs and other elements protruding from base stems and generate instructions for them.") },
429 { N_("InstructBallTerminals"), pr_bool, &instruct_ball_terminals, NULL, NULL, '\0', NULL, 0, N_("Generate instructions for ball terminals.") },
430 { N_("InterpolateStrongPoints"), pr_bool, &interpolate_strong, NULL, NULL, '\0', NULL, 0, N_("Interpolate between stem edges some important points, not affected by other instructions.") },
431 { N_("CounterControl"), pr_bool, &control_counters, NULL, NULL, '\0', NULL, 0, N_("Make sure similar or equal counters remain the same in gridfitted outlines.\nEnabling this option may result in glyph advance widths being\ninconsistently scaled at some PPEMs.") },
432 PREFS_LIST_EMPTY
433 },
434 opentype_list[] = {
435 { N_("UseNewIndicScripts"), pr_bool, &use_second_indic_scripts, NULL, NULL, 'C', NULL, 0, N_("MS has changed (in August 2006) the inner workings of their Indic shaping\nengine, and to disambiguate this change has created a parallel set of script\ntags (generally ending in '2') for Indic writing systems. If you are working\nwith the new system set this flag, if you are working with the old unset it.\n(if you aren't doing Indic work, this flag is irrelevant).") },
436 PREFS_LIST_EMPTY
437 },
438 /* These are hidden, so will never appear in preference ui, hence, no "N_(" */
439 /* They are controled elsewhere AntiAlias is a menu item in the font window's View menu */
440 /* etc. */
441 hidden_list[] = {
442 { "AntiAlias", pr_bool, &default_fv_antialias, NULL, NULL, '\0', NULL, 1, NULL },
443 { "DefaultFVShowHmetrics", pr_int, &default_fv_showhmetrics, NULL, NULL, '\0', NULL, 1, NULL },
444 { "DefaultFVShowVmetrics", pr_int, &default_fv_showvmetrics, NULL, NULL, '\0', NULL, 1, NULL },
445 { "DefaultFVSize", pr_int, &default_fv_font_size, NULL, NULL, 'S', NULL, 1, NULL },
446 { "DefaultFVRowCount", pr_int, &default_fv_row_count, NULL, NULL, 'S', NULL, 1, NULL },
447 { "DefaultFVColCount", pr_int, &default_fv_col_count, NULL, NULL, 'S', NULL, 1, NULL },
448 { "DefaultFVGlyphLabel", pr_int, &default_fv_glyphlabel, NULL, NULL, 'S', NULL, 1, NULL },
449 { "SaveToDir", pr_int, &save_to_dir, NULL, NULL, 'S', NULL, 1, NULL },
450 { "OnlyCopyDisplayed", pr_bool, &onlycopydisplayed, NULL, NULL, '\0', NULL, 1, NULL },
451 { "PalettesDocked", pr_bool, &palettes_docked, NULL, NULL, '\0', NULL, 1, NULL },
452 { "DefaultCVWidth", pr_int, &cv_width, NULL, NULL, '\0', NULL, 1, NULL },
453 { "DefaultCVHeight", pr_int, &cv_height, NULL, NULL, '\0', NULL, 1, NULL },
454 { "CVVisible0", pr_bool, &cvvisible[0], NULL, NULL, '\0', NULL, 1, NULL },
455 { "CVVisible1", pr_bool, &cvvisible[1], NULL, NULL, '\0', NULL, 1, NULL },
456 { "BVVisible0", pr_bool, &bvvisible[0], NULL, NULL, '\0', NULL, 1, NULL },
457 { "BVVisible1", pr_bool, &bvvisible[1], NULL, NULL, '\0', NULL, 1, NULL },
458 { "BVVisible2", pr_bool, &bvvisible[2], NULL, NULL, '\0', NULL, 1, NULL },
459 { "MarkExtrema", pr_int, &CVShows.markextrema, NULL, NULL, '\0', NULL, 1, NULL },
460 { "MarkPointsOfInflect", pr_int, &CVShows.markpoi, NULL, NULL, '\0', NULL, 1, NULL },
461 { "ShowRulers", pr_bool, &CVShows.showrulers, NULL, NULL, '\0', NULL, 1, N_("Display rulers in the Outline Glyph View") },
462 { "ShowCPInfo", pr_int, &CVShows.showcpinfo, NULL, NULL, '\0', NULL, 1, NULL },
463 { "CreateDraggingComparisonOutline", pr_int, &prefs_create_dragging_comparison_outline, NULL, NULL, '\0', NULL, 1, NULL },
464 { "InfoWindowDistance", pr_int, &infowindowdistance, NULL, NULL, '\0', NULL, 1, NULL },
465 { "ShowSideBearings", pr_int, &CVShows.showsidebearings, NULL, NULL, '\0', NULL, 1, NULL },
466 { "ShowRefNames", pr_int, &CVShows.showrefnames, NULL, NULL, '\0', NULL, 1, NULL },
467 { "ShowPoints", pr_bool, &CVShows.showpoints, NULL, NULL, '\0', NULL, 1, NULL },
468 { "ShowFilled", pr_int, &CVShows.showfilled, NULL, NULL, '\0', NULL, 1, NULL },
469 { "ShowTabs", pr_int, &CVShows.showtabs, NULL, NULL, '\0', NULL, 1, NULL },
470 { "SnapOutlines", pr_int, &CVShows.snapoutlines, NULL, NULL, '\0', NULL, 1, NULL },
471 { "ShowAlmostHVLines", pr_bool, &CVShows.showalmosthvlines, NULL, NULL, '\0', NULL, 1, NULL },
472 { "ShowAlmostHVCurves", pr_bool, &CVShows.showalmosthvcurves, NULL, NULL, '\0', NULL, 1, NULL },
473 { "AlmostHVBound", pr_int, &CVShows.hvoffset, NULL, NULL, '\0', NULL, 1, NULL },
474 { "CheckSelfIntersects", pr_bool, &CVShows.checkselfintersects, NULL, NULL, '\0', NULL, 1, NULL },
475 { "ShowDebugChanges", pr_bool, &CVShows.showdebugchanges, NULL, NULL, '\0', NULL, 1, NULL },
476 { "DefaultScreenDpiSystem", pr_int, &oldsystem, NULL, NULL, '\0', NULL, 1, NULL },
477 { "DefaultOutputFormat", pr_int, &oldformatstate, NULL, NULL, '\0', NULL, 1, NULL },
478 { "DefaultBitmapFormat", pr_int, &oldbitmapstate, NULL, NULL, '\0', NULL, 1, NULL },
479 { "SaveValidate", pr_int, &old_validate, NULL, NULL, '\0', NULL, 1, NULL },
480 { "SaveFontLogAsk", pr_int, &old_fontlog, NULL, NULL, '\0', NULL, 1, NULL },
481 { "DefaultSFNTflags", pr_int, &old_sfnt_flags, NULL, NULL, '\0', NULL, 1, NULL },
482 { "DefaultPSflags", pr_int, &old_ps_flags, NULL, NULL, '\0', NULL, 1, NULL },
483 { "PageWidth", pr_int, &pagewidth, NULL, NULL, '\0', NULL, 1, NULL },
484 { "PageHeight", pr_int, &pageheight, NULL, NULL, '\0', NULL, 1, NULL },
485 { "PrintType", pr_int, &printtype, NULL, NULL, '\0', NULL, 1, NULL },
486 { "PrintCommand", pr_string, &printcommand, NULL, NULL, '\0', NULL, 1, NULL },
487 { "PageLazyPrinter", pr_string, &printlazyprinter, NULL, NULL, '\0', NULL, 1, NULL },
488 { "RegularStar", pr_bool, ®ular_star, NULL, NULL, '\0', NULL, 1, NULL },
489 { "PolyStar", pr_bool, &polystar, NULL, NULL, '\0', NULL, 1, NULL },
490 { "RectEllipse", pr_bool, &rectelipse, NULL, NULL, '\0', NULL, 1, NULL },
491 { "RectCenterOut", pr_bool, ¢er_out[0], NULL, NULL, '\0', NULL, 1, NULL },
492 { "EllipseCenterOut", pr_bool, ¢er_out[1], NULL, NULL, '\0', NULL, 1, NULL },
493 { "PolyStartPointCnt", pr_int, &ps_pointcnt, NULL, NULL, '\0', NULL, 1, NULL },
494 { "RoundRectRadius", pr_real, &rr_radius, NULL, NULL, '\0', NULL, 1, NULL },
495 { "StarPercent", pr_real, &star_percent, NULL, NULL, '\0', NULL, 1, NULL },
496 { "CoverageFormatsAllowed", pr_int, &coverageformatsallowed, NULL, NULL, '\0', NULL, 1, NULL },
497 { "DebugWins", pr_int, &debug_wins, NULL, NULL, '\0', NULL, 1, NULL },
498 { "GridFitDpi", pr_int, &gridfit_dpi, NULL, NULL, '\0', NULL, 1, NULL },
499 { "GridFitDepth", pr_int, &gridfit_depth, NULL, NULL, '\0', NULL, 1, NULL },
500 { "GridFitPointSize", pr_real, &gridfit_pointsizey, NULL, NULL, '\0', NULL, 1, NULL },
501 { "GridFitPointSizeX", pr_real, &gridfit_pointsizex, NULL, NULL, '\0', NULL, 1, NULL },
502 { "GridFitSameAs", pr_int, &gridfit_x_sameas_y, NULL, NULL, '\0', NULL, 1, NULL },
503 { "MVShowGrid", pr_int, &mvshowgrid, NULL, NULL, '\0', NULL, 1, NULL },
504 { "ForceNamesWhenOpening", pr_namelist, &force_names_when_opening, NULL, NULL, '\0', NULL, 1, NULL },
505 { "ForceNamesWhenSaving", pr_namelist, &force_names_when_saving, NULL, NULL, '\0', NULL, 1, NULL },
506 { "DefaultFontFilterIndex", pr_int, &default_font_filter_index, NULL, NULL, '\0', NULL, 1, NULL },
507 { "FCShowHidden", pr_bool, &gfc_showhidden, NULL, NULL, '\0', NULL, 1, NULL },
508 { "FCDirPlacement", pr_int, &gfc_dirplace, NULL, NULL, '\0', NULL, 1, NULL },
509 { "FCBookmarks", pr_string, &gfc_bookmarks, NULL, NULL, '\0', NULL, 1, NULL },
510 { "DefaultMVType", pr_int, &mv_type, NULL, NULL, '\0', NULL, 1, NULL },
511 { "DefaultMVWidth", pr_int, &mv_width, NULL, NULL, '\0', NULL, 1, NULL },
512 { "DefaultMVHeight", pr_int, &mv_height, NULL, NULL, '\0', NULL, 1, NULL },
513 { "DefaultBVWidth", pr_int, &bv_width, NULL, NULL, '\0', NULL, 1, NULL },
514 { "DefaultBVHeight", pr_int, &bv_height, NULL, NULL, '\0', NULL, 1, NULL },
515 { "AnchorControlPixelSize", pr_int, &aa_pixelsize, NULL, NULL, '\0', NULL, 1, NULL },
516 #ifdef _NO_LIBCAIRO
517 { "UseCairoDrawing", pr_bool, &prefs_usecairo, NULL, NULL, '\0', NULL, 0, N_("Use the cairo library for drawing (if available)\nThis makes for prettier (anti-aliased) but slower drawing\nThis applies to any windows created AFTER this is set.\nAlready existing windows will continue as they are.") },
518 #endif
519 { "CV_B1Tool", pr_int, (int *) &cv_b1_tool, NULL, NULL, '\0', NULL, 1, NULL },
520 { "CV_CB1Tool", pr_int, (int *) &cv_cb1_tool, NULL, NULL, '\0', NULL, 1, NULL },
521 { "CV_B2Tool", pr_int, (int *) &cv_b2_tool, NULL, NULL, '\0', NULL, 1, NULL },
522 { "CV_CB2Tool", pr_int, (int *) &cv_cb2_tool, NULL, NULL, '\0', NULL, 1, NULL },
523 { "XUID-Base", pr_string, &xuid, NULL, NULL, 'X', NULL, 0, N_("If specified this should be a space separated list of integers each\nless than 16777216 which uniquely identify your organization\nFontForge will generate a random number for the final component.") }, /* Obsolete */
524 { "ShowKerningPane", pr_int, (int *) &show_kerning_pane_in_class, NULL, NULL, '\0', NULL, 1, NULL },
525 PREFS_LIST_EMPTY
526 },
527 oldnames[] = {
528 { "DumpGlyphMap", pr_bool, &glyph_2_name_map, NULL, NULL, '\0', NULL, 0, N_("When generating a truetype or opentype font it is occasionally\nuseful to know the mapping between truetype glyph ids and\nglyph names. Setting this option will cause FontForge to\nproduce a file (with extension .g2n) containing those data.") },
529 { "DefaultTTFApple", pr_int, &pointless, NULL, NULL, '\0', NULL, 1, NULL },
530 { "AcuteCenterBottom", pr_bool, &GraveAcuteCenterBottom, NULL, NULL, '\0', NULL, 1, N_("When placing grave and acute accents above letters, should\nFontForge center them based on their full width, or\nshould it just center based on the lowest point\nof the accent.") },
531 { "AlwaysGenApple", pr_bool, &alwaysgenapple, NULL, NULL, 'A', NULL, 0, N_("Apple and MS/Adobe differ about the format of truetype and opentype files.\nThis controls the default setting of the Apple checkbox in the\nFile->Generate Font dialog.\nThe main differences are:\n Bitmap data are stored in different tables\n Scaled composite glyphs are treated differently\n Use of GSUB rather than morx(t)/feat\n Use of GPOS rather than kern/opbd\n Use of GDEF rather than lcar/prop\nIf both this and OpenType are set, both formats are generated") },
532 { "AlwaysGenOpenType", pr_bool, &alwaysgenopentype, NULL, NULL, 'O', NULL, 0, N_("Apple and MS/Adobe differ about the format of truetype and opentype files.\nThis controls the default setting of the OpenType checkbox in the\nFile->Generate Font dialog.\nThe main differences are:\n Bitmap data are stored in different tables\n Scaled composite glyphs are treated differently\n Use of GSUB rather than morx(t)/feat\n Use of GPOS rather than kern/opbd\n Use of GDEF rather than lcar/prop\nIf both this and Apple are set, both formats are generated") },
533 { "DefaultTTFflags", pr_int, &old_ttf_flags, NULL, NULL, '\0', NULL, 1, NULL },
534 { "DefaultOTFflags", pr_int, &old_otf_flags, NULL, NULL, '\0', NULL, 1, NULL },
535 PREFS_LIST_EMPTY
536 },
537 *prefs_list[] = { general_list, new_list, open_list, navigation_list, sync_list, editing_list, editing_interface_list, accent_list, args_list, fontinfo_list, generate_list, tt_list, opentype_list, hints_list, instrs_list,
538 hidden_list, NULL },
539 *load_prefs_list[] = { general_list, new_list, open_list, navigation_list, sync_list, editing_list, editing_interface_list, accent_list, args_list, fontinfo_list, generate_list, tt_list, opentype_list, hints_list, instrs_list,
540 hidden_list, oldnames, NULL };
541
542 struct visible_prefs_list { char *tab_name; int nest; struct prefs_list *pl; } visible_prefs_list[] = {
543 { N_("Generic"), 0, general_list},
544 { N_("New Font"), 0, new_list},
545 { N_("Open Font"), 0, open_list},
546 { N_("Navigation"), 0, navigation_list},
547 { N_("Editing"), 0, editing_list},
548 { N_("Interface"), 1, editing_interface_list},
549 { N_("Synchronize"), 1, sync_list},
550 { N_("TT"), 1, tt_list},
551 { N_("Accents"), 1, accent_list},
552 { N_("Apps"), 1, args_list},
553 { N_("Font Info"), 0, fontinfo_list},
554 { N_("Generate"), 0, generate_list},
555 { N_("PS Hints"), 1, hints_list},
556 { N_("TT Instrs"), 1, instrs_list},
557 { N_("OpenType"), 1, opentype_list},
558 { NULL, 0, NULL }
559 };
560
FileChooserPrefsChanged(void * pointless)561 static void FileChooserPrefsChanged(void *pointless) {
562 SavePrefs(true);
563 }
564
ProcessFileChooserPrefs(void)565 static void ProcessFileChooserPrefs(void) {
566 unichar_t **b;
567 int i;
568
569 GFileChooserSetShowHidden(gfc_showhidden);
570 GFileChooserSetDirectoryPlacement(gfc_dirplace);
571 if ( gfc_bookmarks==NULL ) {
572 b = malloc(8*sizeof(unichar_t *));
573 i = 0;
574 #ifdef __Mac
575 b[i++] = uc_copy("~/Library/Fonts/");
576 #endif
577 b[i++] = uc_copy("~/fonts");
578 #ifdef __Mac
579 b[i++] = uc_copy("/Library/Fonts/");
580 b[i++] = uc_copy("/System/Library/Fonts/");
581 #endif
582 #if __CygWin
583 b[i++] = uc_copy("/usr/share/fonts/");
584 b[i++] = uc_copy("/usr/share/X11/fonts/");
585 #else
586 b[i++] = uc_copy("/usr/X11R6/lib/X11/fonts/");
587 #endif
588 b[i++] = NULL;
589 GFileChooserSetBookmarks(b);
590 } else {
591 char *pt, *start;
592 start = gfc_bookmarks;
593 for ( i=0; ; ++i ) {
594 pt = strchr(start,';');
595 if ( pt==NULL )
596 break;
597 start = pt+1;
598 }
599 start = gfc_bookmarks;
600 b = malloc((i+2)*sizeof(unichar_t *));
601 for ( i=0; ; ++i ) {
602 pt = strchr(start,';');
603 if ( pt!=NULL )
604 *pt = '\0';
605 b[i] = utf82u_copy(start);
606 if ( pt==NULL )
607 break;
608 *pt = ';';
609 start = pt+1;
610 }
611 b[i+1] = NULL;
612 GFileChooserSetBookmarks(b);
613 }
614 GFileChooserSetPrefsChangedCallback(NULL,FileChooserPrefsChanged);
615 }
616
GetFileChooserPrefs(void)617 static void GetFileChooserPrefs(void) {
618 unichar_t **foo;
619
620 gfc_showhidden = GFileChooserGetShowHidden();
621 gfc_dirplace = GFileChooserGetDirectoryPlacement();
622 foo = GFileChooserGetBookmarks();
623 free(gfc_bookmarks);
624 if ( foo==NULL || foo[0]==NULL )
625 gfc_bookmarks = NULL;
626 else {
627 int i,len=0;
628 for ( i=0; foo[i]!=NULL; ++i )
629 len += 4*u_strlen(foo[i])+1;
630 gfc_bookmarks = malloc(len+10);
631 len = 0;
632 for ( i=0; foo[i]!=NULL; ++i ) {
633 u2utf8_strcpy(gfc_bookmarks+len,foo[i]);
634 len += strlen(gfc_bookmarks+len);
635 gfc_bookmarks[len++] = ';';
636 }
637 if ( len>0 )
638 gfc_bookmarks[len-1] = '\0';
639 else {
640 free(gfc_bookmarks);
641 gfc_bookmarks = NULL;
642 }
643 }
644 }
645
646 #define TOPICS (sizeof(visible_prefs_list)/sizeof(visible_prefs_list[0])-1)
647
PrefsUI_GetPrefs(char * name,Val * val)648 static int PrefsUI_GetPrefs(char *name,Val *val) {
649 int i,j;
650
651 /* Support for obsolete preferences */
652 alwaysgenapple=(old_sfnt_flags&ttf_flag_applemode)?1:0;
653 alwaysgenopentype=(old_sfnt_flags&ttf_flag_otmode)?1:0;
654
655 for ( i=0; prefs_list[i]!=NULL; ++i ) for ( j=0; prefs_list[i][j].name!=NULL; ++j ) {
656 if ( strcmp(prefs_list[i][j].name,name)==0 ) {
657 struct prefs_list *pf = &prefs_list[i][j];
658 if ( pf->type == pr_bool || pf->type == pr_int || pf->type == pr_unicode ) {
659 val->type = v_int;
660 val->u.ival = *((int *) (pf->val));
661 } else if ( pf->type == pr_string || pf->type == pr_file ) {
662 val->type = v_str;
663
664 char *tmpstr = pf->val ? *((char **) (pf->val)) : (char *) (pf->get)();
665 val->u.sval = copy( tmpstr ? tmpstr : "" );
666
667 if( ! pf->val )
668 free( tmpstr );
669 } else if ( pf->type == pr_encoding ) {
670 val->type = v_str;
671 if ( *((NameList **) (pf->val))==NULL )
672 val->u.sval = copy( "NULL" );
673 else
674 val->u.sval = copy( (*((Encoding **) (pf->val)))->enc_name );
675 } else if ( pf->type == pr_namelist ) {
676 val->type = v_str;
677 val->u.sval = copy( (*((NameList **) (pf->val)))->title );
678 } else if ( pf->type == pr_real || pf->type == pr_angle ) {
679 val->type = v_real;
680 val->u.fval = *((float *) (pf->val));
681 if ( pf->type == pr_angle )
682 val->u.fval *= RAD2DEG;
683 } else
684 return( false );
685
686 return( true );
687 }
688 }
689 return( false );
690 }
691
CheckObsoletePrefs(void)692 static void CheckObsoletePrefs(void) {
693 if ( alwaysgenapple==false ) {
694 old_sfnt_flags &= ~ttf_flag_applemode;
695 } else if ( alwaysgenapple==true ) {
696 old_sfnt_flags |= ttf_flag_applemode;
697 }
698 if ( alwaysgenopentype==false ) {
699 old_sfnt_flags &= ~ttf_flag_otmode;
700 } else if ( alwaysgenopentype==true ) {
701 old_sfnt_flags |= ttf_flag_otmode;
702 }
703 if ( old_ttf_flags!=0 )
704 old_sfnt_flags = old_ttf_flags | old_otf_flags;
705 }
706
PrefsUI_SetPrefs(char * name,Val * val1,Val * val2)707 static int PrefsUI_SetPrefs(char *name,Val *val1, Val *val2) {
708 int i,j;
709
710 /* Support for obsolete preferences */
711 alwaysgenapple=-1; alwaysgenopentype=-1;
712
713 for ( i=0; prefs_list[i]!=NULL; ++i ) for ( j=0; prefs_list[i][j].name!=NULL; ++j ) {
714 if ( strcmp(prefs_list[i][j].name,name)==0 ) {
715 struct prefs_list *pf = &prefs_list[i][j];
716 if ( pf->type == pr_bool || pf->type == pr_int || pf->type == pr_unicode ) {
717 if ( (val1->type!=v_int && val1->type!=v_unicode) || val2!=NULL )
718 return( -1 );
719 *((int *) (pf->val)) = val1->u.ival;
720 } else if ( pf->type == pr_real || pf->type == pr_angle ) {
721 if ( val1->type==v_real && val2==NULL )
722 *((float *) (pf->val)) = val1->u.fval;
723 else if ( val1->type!=v_int || (val2!=NULL && val2->type!=v_int ))
724 return( -1 );
725 else
726 *((float *) (pf->val)) = (val2==NULL ? val1->u.ival : val1->u.ival / (double) val2->u.ival);
727 if ( pf->type == pr_angle )
728 *((float *) (pf->val)) /= RAD2DEG;
729 } else if ( pf->type == pr_string || pf->type == pr_file ) {
730 if ( val1->type!=v_str || val2!=NULL )
731 return( -1 );
732 if ( pf->set ) {
733 pf->set( val1->u.sval );
734 } else {
735 free( *((char **) (pf->val)));
736 *((char **) (pf->val)) = copy( val1->u.sval );
737 }
738 } else if ( pf->type == pr_encoding ) {
739 if ( val2!=NULL )
740 return( -1 );
741 else if ( val1->type==v_str && pf->val == &default_encoding) {
742 Encoding *enc = FindOrMakeEncoding(val1->u.sval);
743 if ( enc==NULL )
744 return( -1 );
745 *((Encoding **) (pf->val)) = enc;
746 } else
747 return( -1 );
748 } else if ( pf->type == pr_namelist ) {
749 if ( val2!=NULL )
750 return( -1 );
751 else if ( val1->type==v_str ) {
752 NameList *nl = NameListByName(val1->u.sval);
753 if ( strcmp(val1->u.sval,"NULL")==0 && pf->val != &namelist_for_new_fonts )
754 nl = NULL;
755 else if ( nl==NULL )
756 return( -1 );
757 *((NameList **) (pf->val)) = nl;
758 } else
759 return( -1 );
760 } else
761 return( false );
762
763 CheckObsoletePrefs();
764 SavePrefs(true);
765 return( true );
766 }
767 }
768 return( false );
769 }
770
getPfaEditPrefs(void)771 static char *getPfaEditPrefs(void) {
772 static char *prefs=NULL;
773 char buffer[1025];
774 char *ffdir;
775
776 if ( prefs!=NULL )
777 return prefs;
778 ffdir = getFontForgeUserDir(Config);
779 if ( ffdir==NULL )
780 return NULL;
781 sprintf(buffer,"%s/prefs", ffdir);
782 free(ffdir);
783 prefs = copy(buffer);
784 return prefs;
785 }
786
PrefsUI_getFontForgeShareDir(void)787 static char *PrefsUI_getFontForgeShareDir(void) {
788 return getShareDir();
789 }
790
encmatch(const char * enc,int subok)791 static int encmatch(const char *enc,int subok) {
792 static struct { char *name; int enc; } encs[] = {
793 { "US-ASCII", e_usascii },
794 { "ASCII", e_usascii },
795 { "ISO646-NO", e_iso646_no },
796 { "ISO646-SE", e_iso646_se },
797 { "LATIN10", e_iso8859_16 },
798 { "LATIN1", e_iso8859_1 },
799 { "ISO-8859-1", e_iso8859_1 },
800 { "ISO-8859-2", e_iso8859_2 },
801 { "ISO-8859-3", e_iso8859_3 },
802 { "ISO-8859-4", e_iso8859_4 },
803 { "ISO-8859-5", e_iso8859_4 },
804 { "ISO-8859-6", e_iso8859_4 },
805 { "ISO-8859-7", e_iso8859_4 },
806 { "ISO-8859-8", e_iso8859_4 },
807 { "ISO-8859-9", e_iso8859_4 },
808 { "ISO-8859-10", e_iso8859_10 },
809 { "ISO-8859-11", e_iso8859_11 },
810 { "ISO-8859-13", e_iso8859_13 },
811 { "ISO-8859-14", e_iso8859_14 },
812 { "ISO-8859-15", e_iso8859_15 },
813 { "ISO-8859-16", e_iso8859_16 },
814 { "ISO_8859-1", e_iso8859_1 },
815 { "ISO_8859-2", e_iso8859_2 },
816 { "ISO_8859-3", e_iso8859_3 },
817 { "ISO_8859-4", e_iso8859_4 },
818 { "ISO_8859-5", e_iso8859_4 },
819 { "ISO_8859-6", e_iso8859_4 },
820 { "ISO_8859-7", e_iso8859_4 },
821 { "ISO_8859-8", e_iso8859_4 },
822 { "ISO_8859-9", e_iso8859_4 },
823 { "ISO_8859-10", e_iso8859_10 },
824 { "ISO_8859-11", e_iso8859_11 },
825 { "ISO_8859-13", e_iso8859_13 },
826 { "ISO_8859-14", e_iso8859_14 },
827 { "ISO_8859-15", e_iso8859_15 },
828 { "ISO_8859-16", e_iso8859_16 },
829 { "ISO8859-1", e_iso8859_1 },
830 { "ISO8859-2", e_iso8859_2 },
831 { "ISO8859-3", e_iso8859_3 },
832 { "ISO8859-4", e_iso8859_4 },
833 { "ISO8859-5", e_iso8859_4 },
834 { "ISO8859-6", e_iso8859_4 },
835 { "ISO8859-7", e_iso8859_4 },
836 { "ISO8859-8", e_iso8859_4 },
837 { "ISO8859-9", e_iso8859_4 },
838 { "ISO8859-10", e_iso8859_10 },
839 { "ISO8859-11", e_iso8859_11 },
840 { "ISO8859-13", e_iso8859_13 },
841 { "ISO8859-14", e_iso8859_14 },
842 { "ISO8859-15", e_iso8859_15 },
843 { "ISO8859-16", e_iso8859_16 },
844 { "ISO88591", e_iso8859_1 },
845 { "ISO88592", e_iso8859_2 },
846 { "ISO88593", e_iso8859_3 },
847 { "ISO88594", e_iso8859_4 },
848 { "ISO88595", e_iso8859_4 },
849 { "ISO88596", e_iso8859_4 },
850 { "ISO88597", e_iso8859_4 },
851 { "ISO88598", e_iso8859_4 },
852 { "ISO88599", e_iso8859_4 },
853 { "ISO885910", e_iso8859_10 },
854 { "ISO885911", e_iso8859_11 },
855 { "ISO885913", e_iso8859_13 },
856 { "ISO885914", e_iso8859_14 },
857 { "ISO885915", e_iso8859_15 },
858 { "ISO885916", e_iso8859_16 },
859 { "8859_1", e_iso8859_1 },
860 { "8859_2", e_iso8859_2 },
861 { "8859_3", e_iso8859_3 },
862 { "8859_4", e_iso8859_4 },
863 { "8859_5", e_iso8859_4 },
864 { "8859_6", e_iso8859_4 },
865 { "8859_7", e_iso8859_4 },
866 { "8859_8", e_iso8859_4 },
867 { "8859_9", e_iso8859_4 },
868 { "8859_10", e_iso8859_10 },
869 { "8859_11", e_iso8859_11 },
870 { "8859_13", e_iso8859_13 },
871 { "8859_14", e_iso8859_14 },
872 { "8859_15", e_iso8859_15 },
873 { "8859_16", e_iso8859_16 },
874 { "KOI8-R", e_koi8_r },
875 { "KOI8R", e_koi8_r },
876 { "WINDOWS-1252", e_win },
877 { "CP1252", e_win },
878 { "Big5", e_big5 },
879 { "Big-5", e_big5 },
880 { "BigFive", e_big5 },
881 { "Big-Five", e_big5 },
882 { "Big5HKSCS", e_big5hkscs },
883 { "Big5-HKSCS", e_big5hkscs },
884 { "UTF-8", e_utf8 },
885 { "ISO-10646/UTF-8", e_utf8 },
886 { "ISO_10646/UTF-8", e_utf8 },
887 { "UCS2", e_unicode },
888 { "UCS-2", e_unicode },
889 { "UCS-2-INTERNAL", e_unicode },
890 { "ISO-10646", e_unicode },
891 { "ISO_10646", e_unicode },
892 /* { "eucJP", e_euc }, */
893 /* { "EUC-JP", e_euc }, */
894 /* { "ujis", ??? }, */
895 /* { "EUC-KR", e_euckorean }, */
896 { NULL, 0 }
897 };
898
899 int i;
900 char buffer[80];
901 #if HAVE_ICONV_H
902 static char *last_complaint;
903
904 iconv_t test;
905 free(iconv_local_encoding_name);
906 iconv_local_encoding_name= NULL;
907 #endif
908
909 if ( strchr(enc,'@')!=NULL && strlen(enc)<sizeof(buffer)-1 ) {
910 strcpy(buffer,enc);
911 *strchr(buffer,'@') = '\0';
912 enc = buffer;
913 }
914
915 for ( i=0; encs[i].name!=NULL; ++i )
916 if ( strmatch(enc,encs[i].name)==0 )
917 return( encs[i].enc );
918
919 if ( subok ) {
920 for ( i=0; encs[i].name!=NULL; ++i )
921 if ( strstrmatch(enc,encs[i].name)!=NULL )
922 return( encs[i].enc );
923
924 #if HAVE_ICONV_H
925 /* I only try to use iconv if the encoding doesn't match one I support*/
926 /* loading iconv unicode data takes a while */
927 test = iconv_open(enc,FindUnicharName());
928 if ( test==(iconv_t) (-1) || test==NULL ) {
929 if ( last_complaint==NULL || strcmp(last_complaint,enc)!=0 ) {
930 fprintf( stderr, "Neither FontForge nor iconv() supports your encoding (%s) we will pretend\n you asked for latin1 instead.\n", enc );
931 free( last_complaint );
932 last_complaint = copy(enc);
933 }
934 } else {
935 if ( last_complaint==NULL || strcmp(last_complaint,enc)!=0 ) {
936 fprintf( stderr, "FontForge does not support your encoding (%s), it will try to use iconv()\n or it will pretend the local encoding is latin1\n", enc );
937 free( last_complaint );
938 last_complaint = copy(enc);
939 }
940 iconv_local_encoding_name= copy(enc);
941 iconv_close(test);
942 }
943 #else
944 fprintf( stderr, "FontForge does not support your encoding (%s), it will pretend the local encoding is latin1\n", enc );
945 #endif
946
947 return( e_iso8859_1 );
948 }
949 return( e_unknown );
950 }
951
DefaultEncoding(void)952 static int DefaultEncoding(void) {
953 const char *loc;
954 int enc;
955
956 #if HAVE_LANGINFO_H
957 loc = nl_langinfo(CODESET);
958 enc = encmatch(loc,false);
959 if ( enc!=e_unknown )
960 return( enc );
961 #endif
962 loc = getenv("LC_ALL");
963 if ( loc==NULL ) loc = getenv("LC_CTYPE");
964 /*if ( loc==NULL ) loc = getenv("LC_MESSAGES");*/
965 if ( loc==NULL ) loc = getenv("LANG");
966
967 if ( loc==NULL )
968 return( e_iso8859_1 );
969
970 enc = encmatch(loc,false);
971 if ( enc==e_unknown ) {
972 loc = strrchr(loc,'.');
973 if ( loc==NULL )
974 return( e_iso8859_1 );
975 enc = encmatch(loc+1,true);
976 }
977 if ( enc==e_unknown )
978 return( e_iso8859_1 );
979
980 return( enc );
981 }
982
DefaultXUID(void)983 static void DefaultXUID(void) {
984 /* Adobe has assigned PfaEdit a base XUID of 1021. Each new user is going */
985 /* to get a couple of random numbers appended to that, hoping that will */
986 /* make for a fairly safe system. */
987 /* FontForge will use the same scheme */
988 int r1, r2;
989 char buffer[50];
990 struct timeval tv;
991
992 gettimeofday(&tv,NULL);
993 srand(tv.tv_usec);
994 do {
995 r1 = rand()&0x3ff;
996 } while ( r1==0 ); /* I reserve "0" for me! */
997 gettimeofday(&tv,NULL);
998 g_random_set_seed(tv.tv_usec+1);
999 r2 = g_random_int();
1000 sprintf( buffer, "1021 %d %d", r1, r2 );
1001 if (xuid != NULL) free(xuid);
1002 xuid = copy(buffer);
1003 }
1004
PrefsUI_SetDefaults(void)1005 static void PrefsUI_SetDefaults(void) {
1006
1007 DefaultXUID();
1008 local_encoding = DefaultEncoding();
1009 }
1010
ParseMacMapping(char * pt,struct macsettingname * ms)1011 static void ParseMacMapping(char *pt,struct macsettingname *ms) {
1012 char *end;
1013
1014 ms->mac_feature_type = strtol(pt,&end,10);
1015 if ( *end==',' ) ++end;
1016 ms->mac_feature_setting = strtol(end,&end,10);
1017 if ( *end==' ' ) ++end;
1018 ms->otf_tag =
1019 ((end[0]&0xff)<<24) |
1020 ((end[1]&0xff)<<16) |
1021 ((end[2]&0xff)<<8) |
1022 (end[3]&0xff);
1023 }
1024
ParseNewMacFeature(FILE * p,char * line)1025 static void ParseNewMacFeature(FILE *p,char *line) {
1026 fseek(p,-(strlen(line)-strlen("MacFeat:")),SEEK_CUR);
1027 line[strlen("MacFeat:")] ='\0';
1028 default_mac_feature_map = SFDParseMacFeatures(p,line);
1029 fseek(p,-strlen(line),SEEK_CUR);
1030 if ( user_mac_feature_map!=NULL )
1031 MacFeatListFree(user_mac_feature_map);
1032 user_mac_feature_map = default_mac_feature_map;
1033 }
1034
PrefsUI_LoadPrefs_FromFile(char * filename)1035 static void PrefsUI_LoadPrefs_FromFile( char* filename )
1036 {
1037 FILE *p;
1038 char line[1100];
1039 int i, j, ri=0, mn=0, ms=0, fn=0, ff=0, filt_max=0;
1040 int msp=0, msc=0;
1041 char *pt;
1042 struct prefs_list *pl;
1043
1044 if ( filename!=NULL && (p=fopen(filename,"r"))!=NULL ) {
1045 while ( fgets(line,sizeof(line),p)!=NULL ) {
1046 if ( *line=='#' )
1047 continue;
1048 pt = strchr(line,':');
1049 if ( pt==NULL )
1050 continue;
1051 for ( j=0; load_prefs_list[j]!=NULL; ++j ) {
1052 for ( i=0; load_prefs_list[j][i].name!=NULL; ++i )
1053 if ( strncmp(line,load_prefs_list[j][i].name,pt-line)==0 )
1054 break;
1055 if ( load_prefs_list[j][i].name!=NULL )
1056 break;
1057 }
1058 pl = NULL;
1059 if ( load_prefs_list[j]!=NULL )
1060 pl = &load_prefs_list[j][i];
1061 for ( ++pt; *pt=='\t'; ++pt );
1062 if ( line[strlen(line)-1]=='\n' )
1063 line[strlen(line)-1] = '\0';
1064 if ( line[strlen(line)-1]=='\r' )
1065 line[strlen(line)-1] = '\0';
1066 if ( pl==NULL ) {
1067 if ( strncmp(line,"Recent:",strlen("Recent:"))==0 && ri<RECENT_MAX )
1068 RecentFiles[ri++] = copy(pt);
1069 else if ( strncmp(line,"MenuScript:",strlen("MenuScript:"))==0 && ms<SCRIPT_MENU_MAX )
1070 script_filenames[ms++] = copy(pt);
1071 else if ( strncmp(line,"MenuName:",strlen("MenuName:"))==0 && mn<SCRIPT_MENU_MAX )
1072 script_menu_names[mn++] = utf82u_copy(pt);
1073 else if ( strncmp(line,"FontFilterName:",strlen("FontFilterName:"))==0 ) {
1074 if ( fn>=filt_max )
1075 user_font_filters = realloc(user_font_filters,((filt_max+=10)+1)*sizeof( struct openfilefilters));
1076 user_font_filters[fn].filter = NULL;
1077 user_font_filters[fn++].name = copy(pt);
1078 user_font_filters[fn].name = NULL;
1079 } else if ( strncmp(line,"FontFilter:",strlen("FontFilter:"))==0 ) {
1080 if ( ff<filt_max )
1081 user_font_filters[ff++].filter = copy(pt);
1082 } else if ( strncmp(line,"MacMapCnt:",strlen("MacSetCnt:"))==0 ) {
1083 sscanf( pt, "%d", &msc );
1084 msp = 0;
1085 user_macfeat_otftag = calloc(msc+1,sizeof(struct macsettingname));
1086 } else if ( strncmp(line,"MacMapping:",strlen("MacMapping:"))==0 && msp<msc ) {
1087 ParseMacMapping(pt,&user_macfeat_otftag[msp++]);
1088 } else if ( strncmp(line,"MacFeat:",strlen("MacFeat:"))==0 ) {
1089 ParseNewMacFeature(p,line);
1090 }
1091 continue;
1092 }
1093 switch ( pl->type ) {
1094 case pr_encoding:
1095 { Encoding *enc = FindOrMakeEncoding(pt);
1096 if ( enc==NULL )
1097 enc = FindOrMakeEncoding("ISO8859-1");
1098 if ( enc==NULL )
1099 enc = &custom;
1100 *((Encoding **) (pl->val)) = enc;
1101 }
1102 break;
1103 case pr_namelist:
1104 { NameList *nl = NameListByName(pt);
1105 if ( strcmp(pt,"NULL")==0 && pl->val != &namelist_for_new_fonts )
1106 *((NameList **) (pl->val)) = NULL;
1107 else if ( nl!=NULL )
1108 *((NameList **) (pl->val)) = nl;
1109 }
1110 break;
1111 case pr_bool: case pr_int:
1112 sscanf( pt, "%d", (int *) pl->val );
1113 break;
1114 case pr_unicode:
1115 if ( sscanf( pt, "U+%x", (int *) pl->val )!=1 )
1116 if ( sscanf( pt, "u+%x", (int *) pl->val )!=1 )
1117 sscanf( pt, "%x", (int *) pl->val );
1118 break;
1119 case pr_real: case pr_angle:
1120 { char *end;
1121 *((float *) pl->val) = strtod(pt,&end);
1122 if (( *end==',' || *end=='.' ) ) {
1123 *end = (*end=='.')?',':'.';
1124 *((float *) pl->val) = strtod(pt,NULL);
1125 }
1126 }
1127 if ( pl->type == pr_angle )
1128 *(float *) pl->val /= RAD2DEG;
1129 break;
1130 case pr_string: case pr_file:
1131 if ( *pt=='\0' ) pt=NULL;
1132 if ( pl->val!=NULL )
1133 *((char **) (pl->val)) = copy(pt);
1134 else
1135 (pl->set)(copy(pt));
1136 break;
1137 }
1138 }
1139 fclose(p);
1140 }
1141 }
1142
Prefs_LoadDefaultPreferences(void)1143 void Prefs_LoadDefaultPreferences( void )
1144 {
1145 char filename[PATH_MAX+1];
1146 char* sharedir = getShareDir();
1147
1148 snprintf(filename,PATH_MAX,"%s/prefs", sharedir );
1149 PrefsUI_LoadPrefs_FromFile( filename );
1150 }
1151
1152
PrefsUI_LoadPrefs(void)1153 static void PrefsUI_LoadPrefs(void)
1154 {
1155 char *prefs = getPfaEditPrefs();
1156 FILE *p;
1157 char line[1100], path[PATH_MAX];
1158 int i, j, ri=0, mn=0, ms=0, fn=0, ff=0, filt_max=0;
1159 int msp=0, msc=0;
1160 char *pt, *real_xdefs_filename = NULL;
1161 struct prefs_list *pl;
1162
1163 LoadPfaEditEncodings();
1164 LoadGroupList();
1165
1166 if ( prefs!=NULL && (p=fopen(prefs,"r"))!=NULL ) {
1167 while ( fgets(line,sizeof(line),p)!=NULL ) {
1168 if ( *line=='#' )
1169 continue;
1170 pt = strchr(line,':');
1171 if ( pt==NULL )
1172 continue;
1173 for ( j=0; load_prefs_list[j]!=NULL; ++j ) {
1174 for ( i=0; load_prefs_list[j][i].name!=NULL; ++i )
1175 if ( strncmp(line,load_prefs_list[j][i].name,pt-line)==0 )
1176 break;
1177 if ( load_prefs_list[j][i].name!=NULL )
1178 break;
1179 }
1180 pl = NULL;
1181 if ( load_prefs_list[j]!=NULL )
1182 pl = &load_prefs_list[j][i];
1183 for ( ++pt; *pt=='\t'; ++pt );
1184 if ( line[strlen(line)-1]=='\n' )
1185 line[strlen(line)-1] = '\0';
1186 if ( line[strlen(line)-1]=='\r' )
1187 line[strlen(line)-1] = '\0';
1188 if ( pl==NULL ) {
1189 if ( strncmp(line,"Recent:",strlen("Recent:"))==0 && ri<RECENT_MAX )
1190 RecentFiles[ri++] = copy(pt);
1191 else if ( strncmp(line,"MenuScript:",strlen("MenuScript:"))==0 && ms<SCRIPT_MENU_MAX )
1192 script_filenames[ms++] = copy(pt);
1193 else if ( strncmp(line,"MenuName:",strlen("MenuName:"))==0 && mn<SCRIPT_MENU_MAX )
1194 script_menu_names[mn++] = utf82u_copy(pt);
1195 else if ( strncmp(line,"FontFilterName:",strlen("FontFilterName:"))==0 ) {
1196 if ( fn>=filt_max )
1197 user_font_filters = realloc(user_font_filters,((filt_max+=10)+1)*sizeof( struct openfilefilters));
1198 user_font_filters[fn].filter = NULL;
1199 user_font_filters[fn++].name = copy(pt);
1200 user_font_filters[fn].name = NULL;
1201 } else if ( strncmp(line,"FontFilter:",strlen("FontFilter:"))==0 ) {
1202 if ( ff<filt_max )
1203 user_font_filters[ff++].filter = copy(pt);
1204 } else if ( strncmp(line,"MacMapCnt:",strlen("MacSetCnt:"))==0 ) {
1205 sscanf( pt, "%d", &msc );
1206 msp = 0;
1207 user_macfeat_otftag = calloc(msc+1,sizeof(struct macsettingname));
1208 } else if ( strncmp(line,"MacMapping:",strlen("MacMapping:"))==0 && msp<msc ) {
1209 ParseMacMapping(pt,&user_macfeat_otftag[msp++]);
1210 } else if ( strncmp(line,"MacFeat:",strlen("MacFeat:"))==0 ) {
1211 ParseNewMacFeature(p,line);
1212 }
1213 continue;
1214 }
1215 switch ( pl->type ) {
1216 case pr_encoding:
1217 { Encoding *enc = FindOrMakeEncoding(pt);
1218 if ( enc==NULL )
1219 enc = FindOrMakeEncoding("ISO8859-1");
1220 if ( enc==NULL )
1221 enc = &custom;
1222 *((Encoding **) (pl->val)) = enc;
1223 }
1224 break;
1225 case pr_namelist:
1226 { NameList *nl = NameListByName(pt);
1227 if ( strcmp(pt,"NULL")==0 && pl->val != &namelist_for_new_fonts )
1228 *((NameList **) (pl->val)) = NULL;
1229 else if ( nl!=NULL )
1230 *((NameList **) (pl->val)) = nl;
1231 }
1232 break;
1233 case pr_bool: case pr_int:
1234 sscanf( pt, "%d", (int *) pl->val );
1235 break;
1236 case pr_unicode:
1237 if ( sscanf( pt, "U+%x", (int *) pl->val )!=1 )
1238 if ( sscanf( pt, "u+%x", (int *) pl->val )!=1 )
1239 sscanf( pt, "%x", (int *) pl->val );
1240 break;
1241 case pr_real: case pr_angle:
1242 { char *end;
1243 *((float *) pl->val) = strtod(pt,&end);
1244 if (( *end==',' || *end=='.' ) ) {
1245 *end = (*end=='.')?',':'.';
1246 *((float *) pl->val) = strtod(pt,NULL);
1247 }
1248 }
1249 if ( pl->type == pr_angle )
1250 *(float *) pl->val /= RAD2DEG;
1251 break;
1252 case pr_string: case pr_file:
1253 if ( *pt=='\0' ) pt=NULL;
1254 if ( pl->val!=NULL )
1255 *((char **) (pl->val)) = copy(pt);
1256 else
1257 (pl->set)(copy(pt));
1258 break;
1259 }
1260 }
1261 fclose(p);
1262 }
1263
1264 //
1265 // If the user has no theme set, then use the default
1266 //
1267 real_xdefs_filename = xdefs_filename;
1268 if ( !real_xdefs_filename )
1269 {
1270 // fprintf(stderr,"no xdefs_filename!\n");
1271 // if (!quiet) {
1272 // fprintf(stderr,"TESTING: getPixmapDir:%s\n", getPixmapDir() );
1273 // fprintf(stderr,"TESTING: getShareDir:%s\n", getShareDir() );
1274 // }
1275 snprintf(path, PATH_MAX, "%s/%s", getPixmapDir(), "resources" );
1276 // if (!quiet)
1277 // fprintf(stderr,"trying default theme:%s\n", path );
1278 real_xdefs_filename = path;
1279 }
1280 GResourceAddResourceFile(real_xdefs_filename,GResourceProgramName,true);
1281
1282 if ( othersubrsfile!=NULL && ReadOtherSubrsFile(othersubrsfile)<=0 )
1283 fprintf( stderr, "Failed to read OtherSubrs from %s\n", othersubrsfile );
1284
1285 if ( glyph_2_name_map )
1286 old_sfnt_flags |= ttf_flag_glyphmap;
1287 LoadNamelistDir(NULL);
1288 ProcessFileChooserPrefs();
1289 GDrawEnableCairo( prefs_usecairo );
1290 }
1291
PrefsUI_SavePrefs(int not_if_script)1292 static void PrefsUI_SavePrefs(int not_if_script) {
1293 char *prefs = getPfaEditPrefs();
1294 FILE *p;
1295 int i, j;
1296 char *temp;
1297 struct prefs_list *pl;
1298 extern int running_script;
1299
1300 if ( prefs==NULL )
1301 return;
1302 if ( not_if_script && running_script )
1303 return;
1304
1305 if ( (p=fopen(prefs,"w"))==NULL )
1306 return;
1307
1308 GetFileChooserPrefs();
1309
1310 for ( j=0; prefs_list[j]!=NULL; ++j ) for ( i=0; prefs_list[j][i].name!=NULL; ++i ) {
1311 pl = &prefs_list[j][i];
1312 switch ( pl->type ) {
1313 case pr_encoding:
1314 fprintf( p, "%s:\t%s\n", pl->name, (*((Encoding **) (pl->val)))->enc_name );
1315 break;
1316 case pr_namelist:
1317 fprintf( p, "%s:\t%s\n", pl->name, *((NameList **) (pl->val))==NULL ? "NULL" :
1318 (*((NameList **) (pl->val)))->title );
1319 break;
1320 case pr_bool: case pr_int:
1321 fprintf( p, "%s:\t%d\n", pl->name, *(int *) (pl->val) );
1322 break;
1323 case pr_unicode:
1324 fprintf( p, "%s:\tU+%04x\n", pl->name, *(int *) (pl->val) );
1325 break;
1326 case pr_real:
1327 fprintf( p, "%s:\t%g\n", pl->name, (double) *(float *) (pl->val) );
1328 break;
1329 case pr_string: case pr_file:
1330 if ( (pl->val)!=NULL )
1331 temp = *(char **) (pl->val);
1332 else
1333 temp = (char *) (pl->get());
1334 if ( temp!=NULL )
1335 fprintf( p, "%s:\t%s\n", pl->name, temp );
1336 if ( (pl->val)==NULL )
1337 free(temp);
1338 break;
1339 case pr_angle:
1340 fprintf( p, "%s:\t%g\n", pl->name, ((double) *(float *) pl->val) * RAD2DEG );
1341 break;
1342 }
1343 }
1344
1345 for ( i=0; i<RECENT_MAX && RecentFiles[i]!=NULL; ++i )
1346 fprintf( p, "Recent:\t%s\n", RecentFiles[i]);
1347 for ( i=0; i<SCRIPT_MENU_MAX && script_filenames[i]!=NULL; ++i ) {
1348 fprintf( p, "MenuScript:\t%s\n", script_filenames[i]);
1349 fprintf( p, "MenuName:\t%s\n", temp = u2utf8_copy(script_menu_names[i]));
1350 free(temp);
1351 }
1352 if ( user_font_filters!=NULL ) {
1353 for ( i=0; user_font_filters[i].name!=NULL; ++i ) {
1354 fprintf( p, "FontFilterName:\t%s\n", user_font_filters[i].name);
1355 fprintf( p, "FontFilter:\t%s\n", user_font_filters[i].filter);
1356 }
1357 }
1358 if ( user_macfeat_otftag!=NULL && UserSettingsDiffer()) {
1359 for ( i=0; user_macfeat_otftag[i].otf_tag!=0; ++i );
1360 fprintf( p, "MacMapCnt: %d\n", i );
1361 for ( i=0; user_macfeat_otftag[i].otf_tag!=0; ++i ) {
1362 fprintf( p, "MacMapping: %d,%d %c%c%c%c\n",
1363 user_macfeat_otftag[i].mac_feature_type,
1364 user_macfeat_otftag[i].mac_feature_setting,
1365 (int) (user_macfeat_otftag[i].otf_tag>>24),
1366 (int) ((user_macfeat_otftag[i].otf_tag>>16)&0xff),
1367 (int) ((user_macfeat_otftag[i].otf_tag>>8)&0xff),
1368 (int) (user_macfeat_otftag[i].otf_tag&0xff) );
1369 }
1370 }
1371
1372 if ( UserFeaturesDiffer())
1373 SFDDumpMacFeat(p,default_mac_feature_map);
1374
1375 fclose(p);
1376 }
1377
1378 struct pref_data {
1379 int done;
1380 struct prefs_list* plist;
1381 };
1382
Prefs_ScriptBrowse(GGadget * g,GEvent * e)1383 static int Prefs_ScriptBrowse(GGadget *g, GEvent *e) {
1384 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1385 GWindow gw = GGadgetGetWindow(g);
1386 GGadget *tf = GWidgetGetControl(gw,GGadgetGetCid(g)-SCRIPT_MENU_MAX);
1387 char *cur = GGadgetGetTitle8(tf); char *ret;
1388
1389 if ( *cur=='\0' ) cur=NULL;
1390 ret = gwwv_open_filename(_("Call Script"), cur, "*.pe", NULL);
1391 free(cur);
1392 if ( ret==NULL )
1393 return(true);
1394 GGadgetSetTitle8(tf,ret);
1395 free(ret);
1396 }
1397 return( true );
1398 }
1399
Prefs_BrowseFile(GGadget * g,GEvent * e)1400 static int Prefs_BrowseFile(GGadget *g, GEvent *e) {
1401 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1402 GWindow gw = GGadgetGetWindow(g);
1403 GGadget *tf = GWidgetGetControl(gw,GGadgetGetCid(g)-CID_PrefsBrowseOffset);
1404 char *cur = GGadgetGetTitle8(tf); char *ret;
1405 struct prefs_list *pl = GGadgetGetUserData(tf);
1406
1407 ret = gwwv_open_filename(pl->name, *cur=='\0'? NULL : cur, NULL, NULL);
1408 free(cur);
1409 if ( ret==NULL )
1410 return(true);
1411 GGadgetSetTitle8(tf,ret);
1412 free(ret);
1413 }
1414 return( true );
1415 }
1416
Pref_MappingList(int use_user)1417 static GTextInfo *Pref_MappingList(int use_user) {
1418 struct macsettingname *msn = use_user && user_macfeat_otftag!=NULL ?
1419 user_macfeat_otftag :
1420 macfeat_otftag;
1421 GTextInfo *ti;
1422 int i;
1423 char buf[60];
1424
1425 for ( i=0; msn[i].otf_tag!=0; ++i );
1426 ti = calloc(i+1,sizeof( GTextInfo ));
1427
1428 for ( i=0; msn[i].otf_tag!=0; ++i ) {
1429 sprintf(buf,"%3d,%2d %c%c%c%c",
1430 msn[i].mac_feature_type, msn[i].mac_feature_setting,
1431 (int) (msn[i].otf_tag>>24), (int) ((msn[i].otf_tag>>16)&0xff), (int) ((msn[i].otf_tag>>8)&0xff), (int) (msn[i].otf_tag&0xff) );
1432 ti[i].text = uc_copy(buf);
1433 }
1434 return( ti );
1435 }
1436
GListAddStr(GGadget * list,unichar_t * str,void * ud)1437 void GListAddStr(GGadget *list,unichar_t *str, void *ud) {
1438 int32 i,len;
1439 GTextInfo **ti = GGadgetGetList(list,&len);
1440 GTextInfo **replace = malloc((len+2)*sizeof(GTextInfo *));
1441
1442 replace[len+1] = calloc(1,sizeof(GTextInfo));
1443 for ( i=0; i<len; ++i ) {
1444 replace[i] = malloc(sizeof(GTextInfo));
1445 *replace[i] = *ti[i];
1446 replace[i]->text = u_copy(ti[i]->text);
1447 }
1448 replace[i] = calloc(1,sizeof(GTextInfo));
1449 replace[i]->fg = replace[i]->bg = COLOR_DEFAULT;
1450 replace[i]->text = str;
1451 replace[i]->userdata = ud;
1452 GGadgetSetList(list,replace,false);
1453 }
1454
GListReplaceStr(GGadget * list,int index,unichar_t * str,void * ud)1455 void GListReplaceStr(GGadget *list,int index, unichar_t *str, void *ud) {
1456 int32 i,len;
1457 GTextInfo **ti = GGadgetGetList(list,&len);
1458 GTextInfo **replace = malloc((len+2)*sizeof(GTextInfo *));
1459
1460 for ( i=0; i<len; ++i ) {
1461 replace[i] = malloc(sizeof(GTextInfo));
1462 *replace[i] = *ti[i];
1463 if ( i!=index )
1464 replace[i]->text = u_copy(ti[i]->text);
1465 }
1466 replace[i] = calloc(1,sizeof(GTextInfo));
1467 replace[index]->text = str;
1468 replace[index]->userdata = ud;
1469 GGadgetSetList(list,replace,false);
1470 }
1471
1472 struct setdata {
1473 GWindow gw;
1474 GGadget *list;
1475 GGadget *flist;
1476 GGadget *feature;
1477 GGadget *set_code;
1478 GGadget *otf;
1479 GGadget *ok;
1480 GGadget *cancel;
1481 int index;
1482 int done;
1483 unichar_t *ret;
1484 };
1485
set_e_h(GWindow gw,GEvent * event)1486 static int set_e_h(GWindow gw, GEvent *event) {
1487 struct setdata *sd = GDrawGetUserData(gw);
1488 int i;
1489 int32 len;
1490 GTextInfo **ti;
1491 const unichar_t *ret1; unichar_t *end;
1492 int on, feat, val1, val2;
1493 unichar_t ubuf[4];
1494 char buf[40];
1495
1496 if ( event->type==et_close ) {
1497 sd->done = true;
1498 } else if ( event->type==et_char ) {
1499 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
1500 help("ui/dialogs/prefs.html", "#prefs-features");
1501 return( true );
1502 }
1503 return( false );
1504 } else if ( event->type==et_controlevent && event->u.control.subtype == et_buttonactivate ) {
1505 if ( event->u.control.g == sd->cancel ) {
1506 sd->done = true;
1507 } else if ( event->u.control.g == sd->ok ) {
1508 ret1 = _GGadgetGetTitle(sd->set_code);
1509 on = u_strtol(ret1,&end,10);
1510 if ( *end!='\0' ) {
1511 ff_post_error(_("Bad Number"),_("Bad Number"));
1512 return( true );
1513 }
1514 ret1 = _GGadgetGetTitle(sd->feature);
1515 feat = u_strtol(ret1,&end,10);
1516 if ( *end!='\0' && *end!=' ' ) {
1517 ff_post_error(_("Bad Number"),_("Bad Number"));
1518 return( true );
1519 }
1520 ti = GGadgetGetList(sd->list,&len);
1521 for ( i=0; i<len; ++i ) if ( i!=sd->index ) {
1522 val1 = u_strtol(ti[i]->text,&end,10);
1523 val2 = u_strtol(end+1,NULL,10);
1524 if ( val1==feat && val2==on ) {
1525 static char *buts[3];
1526 buts[0] = _("_Yes");
1527 buts[1] = _("_No");
1528 buts[2] = NULL;
1529 if ( gwwv_ask(_("This feature, setting combination is already used"),(const char **) buts,0,1,
1530 _("This feature, setting combination is already used\nDo you really wish to reuse it?"))==1 )
1531 return( true );
1532 }
1533 }
1534
1535 ret1 = _GGadgetGetTitle(sd->otf);
1536 if ( (ubuf[0] = ret1[0])==0 )
1537 ubuf[0] = ubuf[1] = ubuf[2] = ubuf[3] = ' ';
1538 else if ( (ubuf[1] = ret1[1])==0 )
1539 ubuf[1] = ubuf[2] = ubuf[3] = ' ';
1540 else if ( (ubuf[2] = ret1[2])==0 )
1541 ubuf[2] = ubuf[3] = ' ';
1542 else if ( (ubuf[3] = ret1[3])==0 )
1543 ubuf[3] = ' ';
1544 len = u_strlen(ret1);
1545 if ( len<2 || len>4 || ubuf[0]>=0x7f || ubuf[1]>=0x7f || ubuf[2]>=0x7f || ubuf[3]>=0x7f ) {
1546 ff_post_error(_("Tag too long"),_("Feature tags must be exactly 4 ASCII characters"));
1547 return( true );
1548 }
1549 sprintf(buf,"%3d,%2d %c%c%c%c",
1550 feat, on,
1551 ubuf[0], ubuf[1], ubuf[2], ubuf[3]);
1552 sd->done = true;
1553 sd->ret = uc_copy(buf);
1554 }
1555 }
1556 return( true );
1557 }
1558
AskSetting(struct macsettingname * temp,GGadget * list,int index,GGadget * flist)1559 static unichar_t *AskSetting(struct macsettingname *temp,GGadget *list, int index,GGadget *flist) {
1560 GRect pos;
1561 GWindow gw;
1562 GWindowAttrs wattrs;
1563 GGadgetCreateData gcd[17];
1564 GTextInfo label[17];
1565 struct setdata sd;
1566 char buf[20];
1567 unichar_t ubuf3[6];
1568 int32 len, i;
1569 GTextInfo **ti;
1570
1571 memset(&sd,0,sizeof(sd));
1572 sd.list = list;
1573 sd.flist = flist;
1574 sd.index = index;
1575
1576 memset(&wattrs,0,sizeof(wattrs));
1577 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
1578 wattrs.event_masks = ~(1<<et_charup);
1579 wattrs.restrict_input_to_me = 1;
1580 wattrs.is_dlg = 1;
1581 wattrs.undercursor = 1;
1582 wattrs.cursor = ct_pointer;
1583 wattrs.utf8_window_title = _("Mapping");
1584 pos.x = pos.y = 0;
1585 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,240));
1586 pos.height = GDrawPointsToPixels(NULL,120);
1587 gw = GDrawCreateTopWindow(NULL,&pos,set_e_h,&sd,&wattrs);
1588 sd.gw = gw;
1589
1590 memset(gcd,0,sizeof(gcd));
1591 memset(label,0,sizeof(label));
1592
1593 label[0].text = (unichar_t *) _("_Feature:");
1594 label[0].text_is_1byte = true;
1595 label[0].text_in_resource = true;
1596 gcd[0].gd.label = &label[0];
1597 gcd[0].gd.pos.x = 5; gcd[0].gd.pos.y = 5+4;
1598 gcd[0].gd.flags = gg_enabled|gg_visible;
1599 gcd[0].creator = GLabelCreate;
1600
1601 gcd[1].gd.pos.x = 50; gcd[1].gd.pos.y = 5; gcd[1].gd.pos.width = 170;
1602 gcd[1].gd.flags = gg_enabled|gg_visible;
1603 gcd[1].creator = GListButtonCreate;
1604
1605 label[2].text = (unichar_t *) _("Setting");
1606 label[2].text_is_1byte = true;
1607 gcd[2].gd.label = &label[2];
1608 gcd[2].gd.pos.x = 5; gcd[2].gd.pos.y = gcd[0].gd.pos.y+26;
1609 gcd[2].gd.flags = gg_enabled|gg_visible;
1610 gcd[2].creator = GLabelCreate;
1611
1612 sprintf( buf, "%d", temp->mac_feature_setting );
1613 label[3].text = (unichar_t *) buf;
1614 label[3].text_is_1byte = true;
1615 gcd[3].gd.label = &label[3];
1616 gcd[3].gd.pos.x = gcd[1].gd.pos.x; gcd[3].gd.pos.y = gcd[2].gd.pos.y-4; gcd[3].gd.pos.width = 50;
1617 gcd[3].gd.flags = gg_enabled|gg_visible;
1618 gcd[3].creator = GTextFieldCreate;
1619
1620 label[4].text = (unichar_t *) _("_Tag:");
1621 label[4].text_is_1byte = true;
1622 label[4].text_in_resource = true;
1623 gcd[4].gd.label = &label[4];
1624 gcd[4].gd.pos.x = 5; gcd[4].gd.pos.y = gcd[3].gd.pos.y+26;
1625 gcd[4].gd.flags = gg_enabled|gg_visible;
1626 gcd[4].creator = GLabelCreate;
1627
1628 ubuf3[0] = temp->otf_tag>>24; ubuf3[1] = (temp->otf_tag>>16)&0xff; ubuf3[2] = (temp->otf_tag>>8)&0xff; ubuf3[3] = temp->otf_tag&0xff; ubuf3[4] = 0;
1629 label[5].text = ubuf3;
1630 gcd[5].gd.label = &label[5];
1631 gcd[5].gd.pos.x = gcd[3].gd.pos.x; gcd[5].gd.pos.y = gcd[4].gd.pos.y-4; gcd[5].gd.pos.width = 50;
1632 gcd[5].gd.flags = gg_enabled|gg_visible;
1633 /*gcd[5].gd.u.list = tags;*/
1634 gcd[5].creator = GTextFieldCreate;
1635
1636 gcd[6].gd.pos.x = 13-3; gcd[6].gd.pos.y = gcd[5].gd.pos.y+30;
1637 gcd[6].gd.pos.width = -1; gcd[6].gd.pos.height = 0;
1638 gcd[6].gd.flags = gg_visible | gg_enabled | gg_but_default;
1639 label[6].text = (unichar_t *) _("_OK");
1640 label[6].text_is_1byte = true;
1641 label[6].text_in_resource = true;
1642 gcd[6].gd.label = &label[6];
1643 /*gcd[6].gd.handle_controlevent = Prefs_Ok;*/
1644 gcd[6].creator = GButtonCreate;
1645
1646 gcd[7].gd.pos.x = -13; gcd[7].gd.pos.y = gcd[7-1].gd.pos.y+3;
1647 gcd[7].gd.pos.width = -1; gcd[7].gd.pos.height = 0;
1648 gcd[7].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
1649 label[7].text = (unichar_t *) _("_Cancel");
1650 label[7].text_is_1byte = true;
1651 label[7].text_in_resource = true;
1652 gcd[7].gd.label = &label[7];
1653 gcd[7].creator = GButtonCreate;
1654
1655 GGadgetsCreate(gw,gcd);
1656 sd.feature = gcd[1].ret;
1657 sd.set_code = gcd[3].ret;
1658 sd.otf = gcd[5].ret;
1659 sd.ok = gcd[6].ret;
1660 sd.cancel = gcd[7].ret;
1661
1662 ti = GGadgetGetList(flist,&len);
1663 GGadgetSetList(sd.feature,ti,true);
1664 for ( i=0; i<len; ++i ) {
1665 int val = u_strtol(ti[i]->text,NULL,10);
1666 if ( val==temp->mac_feature_type ) {
1667 GGadgetSetTitle(sd.feature,ti[i]->text);
1668 break;
1669 }
1670 }
1671
1672 GDrawSetVisible(gw,true);
1673 GWidgetIndicateFocusGadget(gcd[1].ret);
1674 while ( !sd.done )
1675 GDrawProcessOneEvent(NULL);
1676 GDrawDestroyWindow(gw);
1677
1678 return( sd.ret );
1679 }
1680
ChangeSetting(GGadget * list,int index,GGadget * flist)1681 static void ChangeSetting(GGadget *list,int index,GGadget *flist) {
1682 struct macsettingname temp;
1683 int32 len;
1684 GTextInfo **ti = GGadgetGetList(list,&len);
1685 char *str;
1686 unichar_t *ustr;
1687
1688 str = cu_copy(ti[index]->text);
1689 ParseMacMapping(str,&temp);
1690 free(str);
1691 if ( (ustr=AskSetting(&temp,list,index,flist))==NULL )
1692 return;
1693 GListReplaceStr(list,index,ustr,NULL);
1694 }
1695
Pref_NewMapping(GGadget * g,GEvent * e)1696 static int Pref_NewMapping(GGadget *g, GEvent *e) {
1697 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1698 GWindow gw = GGadgetGetWindow(g);
1699 GGadget *list = GWidgetGetControl(gw,CID_Mapping);
1700 GGadget *flist = GWidgetGetControl(GDrawGetParentWindow(gw),CID_Features);
1701 struct macsettingname temp;
1702 unichar_t *str;
1703
1704 memset(&temp,0,sizeof(temp));
1705 temp.mac_feature_type = -1;
1706 if ( (str=AskSetting(&temp,list,-1,flist))==NULL )
1707 return( true );
1708 GListAddStr(list,str,NULL);
1709 /*free(str);*/
1710 }
1711 return( true );
1712 }
1713
Pref_DelMapping(GGadget * g,GEvent * e)1714 static int Pref_DelMapping(GGadget *g, GEvent *e) {
1715 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1716 GWindow gw = GGadgetGetWindow(g);
1717 GListDelSelected(GWidgetGetControl(gw,CID_Mapping));
1718 GGadgetSetEnabled(GWidgetGetControl(gw,CID_MappingDel),false);
1719 GGadgetSetEnabled(GWidgetGetControl(gw,CID_MappingEdit),false);
1720 }
1721 return( true );
1722 }
1723
Pref_EditMapping(GGadget * g,GEvent * e)1724 static int Pref_EditMapping(GGadget *g, GEvent *e) {
1725 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1726 GWindow gw = GDrawGetParentWindow(GGadgetGetWindow(g));
1727 GGadget *list = GWidgetGetControl(gw,CID_Mapping);
1728 GGadget *flist = GWidgetGetControl(gw,CID_Features);
1729 ChangeSetting(list,GGadgetGetFirstListSelectedItem(list),flist);
1730 }
1731 return( true );
1732 }
1733
Pref_MappingSel(GGadget * g,GEvent * e)1734 static int Pref_MappingSel(GGadget *g, GEvent *e) {
1735 if ( e->type==et_controlevent && e->u.control.subtype == et_listselected ) {
1736 int32 len;
1737 GTextInfo **ti = GGadgetGetList(g,&len);
1738 GWindow gw = GGadgetGetWindow(g);
1739 int i, sel_cnt=0;
1740 for ( i=0; i<len; ++i )
1741 if ( ti[i]->selected ) ++sel_cnt;
1742 GGadgetSetEnabled(GWidgetGetControl(gw,CID_MappingDel),sel_cnt!=0);
1743 GGadgetSetEnabled(GWidgetGetControl(gw,CID_MappingEdit),sel_cnt==1);
1744 } else if ( e->type==et_controlevent && e->u.control.subtype == et_listdoubleclick ) {
1745 GGadget *flist = GWidgetGetControl( GDrawGetParentWindow(GGadgetGetWindow(g)),CID_Features);
1746 ChangeSetting(g,e->u.control.u.list.changed_index!=-1?e->u.control.u.list.changed_index:
1747 GGadgetGetFirstListSelectedItem(g),flist);
1748 }
1749 return( true );
1750 }
1751
Pref_DefaultMapping(GGadget * g,GEvent * e)1752 static int Pref_DefaultMapping(GGadget *g, GEvent *e) {
1753 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1754 GGadget *list = GWidgetGetControl(GGadgetGetWindow(g),CID_Mapping);
1755 GTextInfo *ti, **arr;
1756 uint16 cnt;
1757
1758 ti = Pref_MappingList(false);
1759 arr = GTextInfoArrayFromList(ti,&cnt);
1760 GGadgetSetList(list,arr,false);
1761 GTextInfoListFree(ti);
1762 }
1763 return( true );
1764 }
1765
Prefs_Ok(GGadget * g,GEvent * e)1766 static int Prefs_Ok(GGadget *g, GEvent *e) {
1767 int i, j, mi;
1768 int err=0, enc;
1769 struct pref_data *p;
1770 GWindow gw;
1771 const unichar_t *ret;
1772 const unichar_t *names[SCRIPT_MENU_MAX], *scripts[SCRIPT_MENU_MAX];
1773 struct prefs_list *pl;
1774 GTextInfo **list;
1775 int32 len;
1776 int maxl, t;
1777 char *str;
1778 real dangle;
1779
1780 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1781 gw = GGadgetGetWindow(g);
1782 p = GDrawGetUserData(gw);
1783 for ( i=0; i<SCRIPT_MENU_MAX; ++i ) {
1784 names[i] = _GGadgetGetTitle(GWidgetGetControl(gw,CID_ScriptMNameBase+i));
1785 scripts[i] = _GGadgetGetTitle(GWidgetGetControl(gw,CID_ScriptMFileBase+i));
1786 if ( *names[i]=='\0' ) names[i] = NULL;
1787 if ( *scripts[i]=='\0' ) scripts[i] = NULL;
1788 if ( scripts[i]==NULL && names[i]!=NULL ) {
1789 ff_post_error(_("Menu name with no associated script"),_("Menu name with no associated script"));
1790 return( true );
1791 } else if ( scripts[i]!=NULL && names[i]==NULL ) {
1792 ff_post_error(_("Script with no associated menu name"),_("Script with no associated menu name"));
1793 return( true );
1794 }
1795 }
1796 for ( i=mi=0; i<SCRIPT_MENU_MAX; ++i ) {
1797 if ( names[i]!=NULL ) {
1798 names[mi] = names[i];
1799 scripts[mi] = scripts[i];
1800 ++mi;
1801 }
1802 }
1803 for ( j=0; visible_prefs_list[j].tab_name!=0; ++j ) for ( i=0; visible_prefs_list[j].pl[i].name!=NULL; ++i ) {
1804 pl = &visible_prefs_list[j].pl[i];
1805 /* before assigning values, check for any errors */
1806 /* if any errors, then NO values should be assigned, in case they cancel */
1807 if ( pl->dontdisplay )
1808 continue;
1809 if ( pl->type==pr_int ) {
1810 GetInt8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
1811 } else if ( pl->type==pr_real ) {
1812 GetReal8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
1813 } else if ( pl->type==pr_angle ) {
1814 dangle = GetReal8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
1815 if ( dangle > 90 || dangle < 0 ) {
1816 GGadgetProtest8(pl->name);
1817 err = true;
1818 }
1819 } else if ( pl->type==pr_unicode ) {
1820 GetUnicodeChar8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
1821 }
1822 }
1823 if ( err )
1824 return( true );
1825
1826 for ( j=0; visible_prefs_list[j].tab_name!=0; ++j ) for ( i=0; visible_prefs_list[j].pl[i].name!=NULL; ++i ) {
1827 pl = &visible_prefs_list[j].pl[i];
1828 if ( pl->dontdisplay )
1829 continue;
1830 switch( pl->type ) {
1831 case pr_int:
1832 *((int *) (pl->val)) = GetInt8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
1833 break;
1834 case pr_unicode:
1835 *((int *) (pl->val)) = GetUnicodeChar8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
1836 break;
1837 case pr_bool:
1838 *((int *) (pl->val)) = GGadgetIsChecked(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
1839 break;
1840 case pr_real:
1841 *((float *) (pl->val)) = GetReal8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
1842 break;
1843 case pr_encoding:
1844 { Encoding *e;
1845 e = ParseEncodingNameFromList(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
1846 if ( e!=NULL )
1847 *((Encoding **) (pl->val)) = e;
1848 enc = 1; /* So gcc doesn't complain about unused. It is unused, but why add the ifdef and make the code even messier? Sigh. icc complains anyway */
1849 }
1850 break;
1851 case pr_namelist:
1852 { NameList *nl;
1853 GTextInfo *ti = GGadgetGetListItemSelected(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
1854 if ( ti!=NULL ) {
1855 char *name = u2utf8_copy(ti->text);
1856 nl = NameListByName(name);
1857 free(name);
1858 if ( nl!=NULL && nl->uses_unicode && !allow_utf8_glyphnames)
1859 ff_post_error(_("Namelist contains non-ASCII names"),_("Glyph names should be limited to characters in the ASCII character set, but there are names in this namelist which use characters outside that range."));
1860 else if ( nl!=NULL )
1861 *((NameList **) (pl->val)) = nl;
1862 }
1863 }
1864 break;
1865 case pr_string: case pr_file:
1866 ret = _GGadgetGetTitle(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
1867 if ( pl->val!=NULL ) {
1868 free( *((char **) (pl->val)) );
1869 *((char **) (pl->val)) = NULL;
1870 if ( ret!=NULL && *ret!='\0' )
1871 *((char **) (pl->val)) = /* u2def_*/ cu_copy(ret);
1872 } else {
1873 char *cret = cu_copy(ret);
1874 (pl->set)(cret);
1875 free(cret);
1876 }
1877 break;
1878 case pr_angle:
1879 *((float *) (pl->val)) = GetReal8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err)/RAD2DEG;
1880 break;
1881 }
1882 }
1883 for ( i=0; i<SCRIPT_MENU_MAX; ++i ) {
1884 free(script_menu_names[i]); script_menu_names[i] = NULL;
1885 free(script_filenames[i]); script_filenames[i] = NULL;
1886 }
1887 for ( i=0; i<mi; ++i ) {
1888 script_menu_names[i] = u_copy(names[i]);
1889 script_filenames[i] = u2def_copy(scripts[i]);
1890 }
1891
1892 list = GGadgetGetList(GWidgetGetControl(gw,CID_Mapping),&len);
1893 UserSettingsFree();
1894 user_macfeat_otftag = malloc((len+1)*sizeof(struct macsettingname));
1895 user_macfeat_otftag[len].otf_tag = 0;
1896 maxl = 0;
1897 for ( i=0; i<len; ++i ) {
1898 t = u_strlen(list[i]->text);
1899 if ( t>maxl ) maxl = t;
1900 }
1901 str = malloc(maxl+3);
1902 for ( i=0; i<len; ++i ) {
1903 u2encoding_strncpy(str,list[i]->text,maxl+1,e_mac);
1904 ParseMacMapping(str,&user_macfeat_otftag[i]);
1905 }
1906 free(str);
1907
1908 Prefs_ReplaceMacFeatures(GWidgetGetControl(gw,CID_Features));
1909
1910 if ( xuid!=NULL ) {
1911 char *pt;
1912 for ( pt=xuid; *pt==' ' ; ++pt );
1913 if ( *pt=='[' ) { /* People who know PS well, might want to put brackets arround the xuid base array, but I don't want them */
1914 pt = copy(pt+1);
1915 if (xuid != NULL) free( xuid );
1916 xuid = pt;
1917 }
1918 for ( pt=xuid+strlen(xuid)-1; pt>xuid && *pt==' '; --pt );
1919 if ( pt >= xuid && *pt==']' ) *pt = '\0';
1920 }
1921
1922 p->done = true;
1923 PrefsUI_SavePrefs(true);
1924 if ( maxundoes==0 ) { FontView *fv;
1925 for ( fv=fv_list ; fv!=NULL; fv=(FontView *) (fv->b.next) )
1926 SFRemoveUndoes(fv->b.sf,NULL,NULL);
1927 }
1928 if ( othersubrsfile!=NULL && ReadOtherSubrsFile(othersubrsfile)<=0 )
1929 fprintf( stderr, "Failed to read OtherSubrs from %s\n", othersubrsfile );
1930 GDrawEnableCairo(prefs_usecairo);
1931
1932 int force_redraw_charviews = 0;
1933 if( prefs_oldval_cvEditHandleSize != prefs_cvEditHandleSize )
1934 force_redraw_charviews = 1;
1935 if( prefs_oldval_cvInactiveHandleAlpha != prefs_cvInactiveHandleAlpha )
1936 force_redraw_charviews = 1;
1937
1938
1939 if( force_redraw_charviews )
1940 {
1941 FontView *fv;
1942 for ( fv=fv_list ; fv!=NULL; fv=(FontView *) (fv->b.next) )
1943 {
1944 FVRedrawAllCharViews( fv );
1945 }
1946 }
1947 }
1948 return( true );
1949 }
1950
Prefs_Cancel(GGadget * g,GEvent * e)1951 static int Prefs_Cancel(GGadget *g, GEvent *e) {
1952 if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1953 struct pref_data *p = GDrawGetUserData(GGadgetGetWindow(g));
1954 MacFeatListFree(GGadgetGetUserData((GWidgetGetControl(
1955 GGadgetGetWindow(g),CID_Features))));
1956 p->done = true;
1957 }
1958 return( true );
1959 }
1960
e_h(GWindow gw,GEvent * event)1961 static int e_h(GWindow gw, GEvent *event) {
1962 if ( event->type==et_close ) {
1963 struct pref_data *p = GDrawGetUserData(gw);
1964 p->done = true;
1965 if(GWidgetGetControl(gw,CID_Features)) {
1966 MacFeatListFree(GGadgetGetUserData((GWidgetGetControl(gw,CID_Features))));
1967 }
1968 } else if ( event->type==et_char ) {
1969 if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
1970 help("ui/dialogs/prefs.html", NULL);
1971 return( true );
1972 }
1973 return( false );
1974 }
1975 return( true );
1976 }
1977
PrefsInit(void)1978 static void PrefsInit(void) {
1979 static int done = false;
1980 int i;
1981
1982 if ( done )
1983 return;
1984 done = true;
1985 for ( i=0; visible_prefs_list[i].tab_name!=NULL; ++i )
1986 visible_prefs_list[i].tab_name = _(visible_prefs_list[i].tab_name);
1987 }
1988
DoPrefs(void)1989 void DoPrefs(void) {
1990 GRect pos;
1991 GWindow gw;
1992 GWindowAttrs wattrs;
1993 GGadgetCreateData *pgcd, gcd[5], sgcd[45], mgcd[3], mfgcd[9], msgcd[9];
1994 GGadgetCreateData mfboxes[3], *mfarray[14];
1995 GGadgetCreateData mpboxes[3], *mparray[14];
1996 GGadgetCreateData sboxes[2], *sarray[50];
1997 GGadgetCreateData mboxes[3], *varray[5], *harray[8];
1998 GTextInfo *plabel, **list, label[5], slabel[45], *plabels[TOPICS+5], mflabels[9], mslabels[9];
1999 GTabInfo aspects[TOPICS+5], subaspects[3];
2000 GGadgetCreateData **hvarray, boxes[2*TOPICS];
2001 struct pref_data p;
2002 int i, gc, sgc, j, k, line, line_max, y, y2, ii, si;
2003 int32 llen;
2004 char buf[20];
2005 int gcnt[20];
2006 static unichar_t nullstr[] = { 0 };
2007 struct prefs_list *pl;
2008 char *tempstr;
2009 FontRequest rq;
2010 GFont *font;
2011
2012 PrefsInit();
2013
2014 MfArgsInit();
2015 for ( k=line_max=0; visible_prefs_list[k].tab_name!=0; ++k ) {
2016 for ( i=line=gcnt[k]=0; visible_prefs_list[k].pl[i].name!=NULL; ++i ) {
2017 if ( visible_prefs_list[k].pl[i].dontdisplay )
2018 continue;
2019 gcnt[k] += 2;
2020 if ( visible_prefs_list[k].pl[i].type==pr_bool ) ++gcnt[k];
2021 else if ( visible_prefs_list[k].pl[i].type==pr_file ) ++gcnt[k];
2022 else if ( visible_prefs_list[k].pl[i].type==pr_angle ) ++gcnt[k];
2023 ++line;
2024 }
2025 if ( visible_prefs_list[k].pl == args_list ) {
2026 gcnt[k] += 6;
2027 line += 6;
2028 }
2029 if ( line>line_max ) line_max = line;
2030 }
2031
2032 prefs_oldval_cvEditHandleSize = prefs_cvEditHandleSize;
2033 prefs_oldval_cvInactiveHandleAlpha = prefs_cvInactiveHandleAlpha;
2034
2035 memset(&p,'\0',sizeof(p));
2036 memset(&wattrs,0,sizeof(wattrs));
2037 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
2038 wattrs.event_masks = ~(1<<et_charup);
2039 wattrs.restrict_input_to_me = 1;
2040 wattrs.is_dlg = 1;
2041 wattrs.undercursor = 1;
2042 wattrs.cursor = ct_pointer;
2043 wattrs.utf8_window_title = _("Preferences");
2044 pos.x = pos.y = 0;
2045 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,350));
2046 pos.height = GDrawPointsToPixels(NULL,line_max*26+69);
2047 gw = GDrawCreateTopWindow(NULL,&pos,e_h,&p,&wattrs);
2048
2049 memset(sgcd,0,sizeof(sgcd));
2050 memset(slabel,0,sizeof(slabel));
2051 memset(&mfgcd,0,sizeof(mfgcd));
2052 memset(&msgcd,0,sizeof(msgcd));
2053 memset(&mflabels,0,sizeof(mflabels));
2054 memset(&mslabels,0,sizeof(mslabels));
2055 memset(&mfboxes,0,sizeof(mfboxes));
2056 memset(&mpboxes,0,sizeof(mpboxes));
2057 memset(&sboxes,0,sizeof(sboxes));
2058 memset(&boxes,0,sizeof(boxes));
2059
2060 GCDFillMacFeat(mfgcd,mflabels,250,default_mac_feature_map, true, mfboxes, mfarray);
2061
2062 sgc = 0;
2063
2064 msgcd[sgc].gd.pos.x = 6; msgcd[sgc].gd.pos.y = 6;
2065 msgcd[sgc].gd.pos.width = 250; msgcd[sgc].gd.pos.height = 16*12+10;
2066 msgcd[sgc].gd.flags = gg_visible | gg_enabled | gg_list_alphabetic | gg_list_multiplesel;
2067 msgcd[sgc].gd.cid = CID_Mapping;
2068 msgcd[sgc].gd.u.list = Pref_MappingList(true);
2069 msgcd[sgc].gd.handle_controlevent = Pref_MappingSel;
2070 msgcd[sgc++].creator = GListCreate;
2071 mparray[0] = &msgcd[sgc-1];
2072
2073 msgcd[sgc].gd.pos.x = 6; msgcd[sgc].gd.pos.y = msgcd[sgc-1].gd.pos.y+msgcd[sgc-1].gd.pos.height+10;
2074 msgcd[sgc].gd.flags = gg_visible | gg_enabled;
2075 mslabels[sgc].text = (unichar_t *) S_("MacMap|_New...");
2076 mslabels[sgc].text_is_1byte = true;
2077 mslabels[sgc].text_in_resource = true;
2078 msgcd[sgc].gd.label = &mslabels[sgc];
2079 msgcd[sgc].gd.handle_controlevent = Pref_NewMapping;
2080 msgcd[sgc++].creator = GButtonCreate;
2081 mparray[4] = GCD_Glue; mparray[5] = &msgcd[sgc-1];
2082
2083 msgcd[sgc].gd.pos.x = msgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
2084 msgcd[sgc].gd.pos.y = msgcd[sgc-1].gd.pos.y;
2085 msgcd[sgc].gd.flags = gg_visible ;
2086 mslabels[sgc].text = (unichar_t *) _("_Delete");
2087 mslabels[sgc].text_is_1byte = true;
2088 mslabels[sgc].text_in_resource = true;
2089 msgcd[sgc].gd.label = &mslabels[sgc];
2090 msgcd[sgc].gd.cid = CID_MappingDel;
2091 msgcd[sgc].gd.handle_controlevent = Pref_DelMapping;
2092 msgcd[sgc++].creator = GButtonCreate;
2093 mparray[5] = GCD_Glue; mparray[6] = &msgcd[sgc-1];
2094
2095 msgcd[sgc].gd.pos.x = msgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
2096 msgcd[sgc].gd.pos.y = msgcd[sgc-1].gd.pos.y;
2097 msgcd[sgc].gd.flags = gg_visible ;
2098 mslabels[sgc].text = (unichar_t *) _("_Edit...");
2099 mslabels[sgc].text_is_1byte = true;
2100 mslabels[sgc].text_in_resource = true;
2101 msgcd[sgc].gd.label = &mslabels[sgc];
2102 msgcd[sgc].gd.cid = CID_MappingEdit;
2103 msgcd[sgc].gd.handle_controlevent = Pref_EditMapping;
2104 msgcd[sgc++].creator = GButtonCreate;
2105 mparray[7] = GCD_Glue; mparray[8] = &msgcd[sgc-1];
2106
2107 msgcd[sgc].gd.pos.x = msgcd[sgc-1].gd.pos.x+10+GIntGetResource(_NUM_Buttonsize)*100/GIntGetResource(_NUM_ScaleFactor);
2108 msgcd[sgc].gd.pos.y = msgcd[sgc-1].gd.pos.y;
2109 msgcd[sgc].gd.flags = gg_visible | gg_enabled;
2110 mslabels[sgc].text = (unichar_t *) S_("MacMapping|Default");
2111 mslabels[sgc].text_is_1byte = true;
2112 mslabels[sgc].text_in_resource = true;
2113 msgcd[sgc].gd.label = &mslabels[sgc];
2114 msgcd[sgc].gd.handle_controlevent = Pref_DefaultMapping;
2115 msgcd[sgc++].creator = GButtonCreate;
2116 mparray[9] = GCD_Glue; mparray[10] = &msgcd[sgc-1];
2117 mparray[11] = GCD_Glue; mparray[12] = NULL;
2118
2119 mpboxes[2].gd.flags = gg_enabled|gg_visible;
2120 mpboxes[2].gd.u.boxelements = mparray+4;
2121 mpboxes[2].creator = GHBoxCreate;
2122 mparray[1] = GCD_Glue;
2123 mparray[2] = &mpboxes[2];
2124 mparray[3] = NULL;
2125
2126 mpboxes[0].gd.flags = gg_enabled|gg_visible;
2127 mpboxes[0].gd.u.boxelements = mparray;
2128 mpboxes[0].creator = GVBoxCreate;
2129
2130 sgc = 0;
2131 y2=5;
2132 si = 0;
2133
2134 slabel[sgc].text = (unichar_t *) _("Menu Name");
2135 slabel[sgc].text_is_1byte = true;
2136 sgcd[sgc].gd.label = &slabel[sgc];
2137 sgcd[sgc].gd.popup_msg = _("You may create a script menu containing up to 10 frequently used scripts.\nEach entry in the menu needs both a name to display in the menu and\na script file to execute. The menu name may contain any unicode characters.\nThe button labeled \"...\" will allow you to browse for a script file.");
2138 sgcd[sgc].gd.pos.x = 8;
2139 sgcd[sgc].gd.pos.y = y2;
2140 sgcd[sgc].gd.flags = gg_visible | gg_enabled;
2141 sgcd[sgc++].creator = GLabelCreate;
2142 sarray[si++] = &sgcd[sgc-1];
2143
2144 slabel[sgc].text = (unichar_t *) _("Script File");
2145 slabel[sgc].text_is_1byte = true;
2146 sgcd[sgc].gd.label = &slabel[sgc];
2147 sgcd[sgc].gd.popup_msg = _("You may create a script menu containing up to 10 frequently used scripts\nEach entry in the menu needs both a name to display in the menu and\na script file to execute. The menu name may contain any unicode characters.\nThe button labeled \"...\" will allow you to browse for a script file.");
2148 sgcd[sgc].gd.pos.x = 110;
2149 sgcd[sgc].gd.pos.y = y2;
2150 sgcd[sgc].gd.flags = gg_visible | gg_enabled;
2151 sgcd[sgc++].creator = GLabelCreate;
2152 sarray[si++] = &sgcd[sgc-1];
2153 sarray[si++] = GCD_Glue;
2154 sarray[si++] = NULL;
2155
2156 y2 += 14;
2157
2158 for ( i=0; i<SCRIPT_MENU_MAX; ++i ) {
2159 sgcd[sgc].gd.pos.x = 8; sgcd[sgc].gd.pos.y = y2;
2160 sgcd[sgc].gd.flags = gg_visible | gg_enabled | gg_text_xim;
2161 slabel[sgc].text = script_menu_names[i]==NULL?nullstr:script_menu_names[i];
2162 sgcd[sgc].gd.label = &slabel[sgc];
2163 sgcd[sgc].gd.cid = i+CID_ScriptMNameBase;
2164 sgcd[sgc++].creator = GTextFieldCreate;
2165 sarray[si++] = &sgcd[sgc-1];
2166
2167 sgcd[sgc].gd.pos.x = 110; sgcd[sgc].gd.pos.y = y2;
2168 sgcd[sgc].gd.flags = gg_visible | gg_enabled;
2169 slabel[sgc].text = (unichar_t *) (script_filenames[i]==NULL?"":script_filenames[i]);
2170 slabel[sgc].text_is_1byte = true;
2171 sgcd[sgc].gd.label = &slabel[sgc];
2172 sgcd[sgc].gd.cid = i+CID_ScriptMFileBase;
2173 sgcd[sgc++].creator = GTextFieldCreate;
2174 sarray[si++] = &sgcd[sgc-1];
2175
2176 sgcd[sgc].gd.pos.x = 210; sgcd[sgc].gd.pos.y = y2;
2177 sgcd[sgc].gd.flags = gg_visible | gg_enabled;
2178 slabel[sgc].text = (unichar_t *) _("...");
2179 slabel[sgc].text_is_1byte = true;
2180 sgcd[sgc].gd.label = &slabel[sgc];
2181 sgcd[sgc].gd.cid = i+CID_ScriptMBrowseBase;
2182 sgcd[sgc].gd.handle_controlevent = Prefs_ScriptBrowse;
2183 sgcd[sgc++].creator = GButtonCreate;
2184 sarray[si++] = &sgcd[sgc-1];
2185 sarray[si++] = NULL;
2186
2187 y2 += 26;
2188 }
2189 sarray[si++] = GCD_Glue; sarray[si++] = GCD_Glue; sarray[si++] = GCD_Glue;
2190 sarray[si++] = NULL;
2191 sarray[si++] = NULL;
2192
2193 sboxes[0].gd.flags = gg_enabled|gg_visible;
2194 sboxes[0].gd.u.boxelements = sarray;
2195 sboxes[0].creator = GHVBoxCreate;
2196
2197 memset(&mgcd,0,sizeof(mgcd));
2198 memset(&mgcd,0,sizeof(mgcd));
2199 memset(&subaspects,'\0',sizeof(subaspects));
2200 memset(&label,0,sizeof(label));
2201 memset(&gcd,0,sizeof(gcd));
2202 memset(&aspects,'\0',sizeof(aspects));
2203 aspects[0].selected = true;
2204
2205 for ( k=0; visible_prefs_list[k].tab_name!=0; ++k ) {
2206 pgcd = calloc(gcnt[k]+4,sizeof(GGadgetCreateData));
2207 plabel = calloc(gcnt[k]+4,sizeof(GTextInfo));
2208 hvarray = calloc((gcnt[k]+6)*5+2,sizeof(GGadgetCreateData *));
2209
2210 aspects[k].text = (unichar_t *) visible_prefs_list[k].tab_name;
2211 aspects[k].text_is_1byte = true;
2212 aspects[k].gcd = &boxes[2*k];
2213 aspects[k].nesting = visible_prefs_list[k].nest;
2214 plabels[k] = plabel;
2215
2216 gc = si = 0;
2217 for ( i=line=0, y=5; visible_prefs_list[k].pl[i].name!=NULL; ++i ) {
2218 pl = &visible_prefs_list[k].pl[i];
2219 if ( pl->dontdisplay )
2220 continue;
2221 plabel[gc].text = (unichar_t *) _(pl->name);
2222 plabel[gc].text_is_1byte = true;
2223 pgcd[gc].gd.label = &plabel[gc];
2224 pgcd[gc].gd.mnemonic = '\0';
2225 pgcd[gc].gd.popup_msg = _(pl->popup);
2226 pgcd[gc].gd.pos.x = 8;
2227 pgcd[gc].gd.pos.y = y + 6;
2228 pgcd[gc].gd.flags = gg_visible | gg_enabled;
2229 pgcd[gc++].creator = GLabelCreate;
2230 hvarray[si++] = &pgcd[gc-1];
2231
2232 plabel[gc].text_is_1byte = true;
2233 pgcd[gc].gd.label = &plabel[gc];
2234 pgcd[gc].gd.mnemonic = '\0';
2235 pgcd[gc].gd.popup_msg = _(pl->popup);
2236 pgcd[gc].gd.pos.x = 110;
2237 pgcd[gc].gd.pos.y = y;
2238 pgcd[gc].gd.flags = gg_visible | gg_enabled;
2239 pgcd[gc].data = pl;
2240 pgcd[gc].gd.cid = k*CID_PrefsOffset+CID_PrefsBase+i;
2241 switch ( pl->type ) {
2242 case pr_bool:
2243 plabel[gc].text = (unichar_t *) _("On");
2244 pgcd[gc].gd.pos.y += 3;
2245 pgcd[gc++].creator = GRadioCreate;
2246 hvarray[si++] = &pgcd[gc-1];
2247 pgcd[gc] = pgcd[gc-1];
2248 pgcd[gc].gd.pos.x += 50;
2249 pgcd[gc].gd.cid = 0;
2250 pgcd[gc].gd.label = &plabel[gc];
2251 plabel[gc].text = (unichar_t *) _("Off");
2252 plabel[gc].text_is_1byte = true;
2253 hvarray[si++] = &pgcd[gc];
2254 hvarray[si++] = GCD_Glue;
2255 if ( *((int *) pl->val))
2256 pgcd[gc-1].gd.flags |= gg_cb_on;
2257 else
2258 pgcd[gc].gd.flags |= gg_cb_on;
2259 ++gc;
2260 y += 22;
2261 break;
2262 case pr_int:
2263 sprintf(buf,"%d", *((int *) pl->val));
2264 plabel[gc].text = (unichar_t *) copy( buf );
2265 pgcd[gc++].creator = GTextFieldCreate;
2266 hvarray[si++] = &pgcd[gc-1];
2267 hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
2268 y += 26;
2269 break;
2270 case pr_unicode:
2271 /*sprintf(buf,"U+%04x", *((int *) pl->val));*/
2272 { char *pt; pt=buf; pt=utf8_idpb(pt,*((int *)pl->val),UTF8IDPB_NOZERO); *pt='\0'; }
2273 plabel[gc].text = (unichar_t *) copy( buf );
2274 pgcd[gc++].creator = GTextFieldCreate;
2275 hvarray[si++] = &pgcd[gc-1];
2276 hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
2277 y += 26;
2278 break;
2279 case pr_real:
2280 sprintf(buf,"%g", *((float *) pl->val));
2281 plabel[gc].text = (unichar_t *) copy( buf );
2282 pgcd[gc++].creator = GTextFieldCreate;
2283 hvarray[si++] = &pgcd[gc-1];
2284 hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
2285 y += 26;
2286 break;
2287 case pr_encoding:
2288 pgcd[gc].gd.u.list = GetEncodingTypes();
2289 pgcd[gc].gd.label = EncodingTypesFindEnc(pgcd[gc].gd.u.list,
2290 *(Encoding **) pl->val);
2291 for ( ii=0; pgcd[gc].gd.u.list[ii].text!=NULL ||pgcd[gc].gd.u.list[ii].line; ++ii )
2292 if ( pgcd[gc].gd.u.list[ii].userdata!=NULL &&
2293 (strcmp(pgcd[gc].gd.u.list[ii].userdata,"Compacted")==0 ||
2294 strcmp(pgcd[gc].gd.u.list[ii].userdata,"Original")==0 ))
2295 pgcd[gc].gd.u.list[ii].disabled = true;
2296 pgcd[gc].creator = GListFieldCreate;
2297 pgcd[gc].gd.pos.width = 160;
2298 if ( pgcd[gc].gd.label==NULL ) pgcd[gc].gd.label = &encodingtypes[0];
2299 ++gc;
2300 hvarray[si++] = &pgcd[gc-1];
2301 hvarray[si++] = GCD_ColSpan; hvarray[si++] = GCD_ColSpan;
2302 y += 28;
2303 break;
2304 case pr_namelist:
2305 { char **nlnames = AllNamelistNames();
2306 int cnt;
2307 GTextInfo *namelistnames;
2308 for ( cnt=0; nlnames[cnt]!=NULL; ++cnt);
2309 namelistnames = calloc(cnt+1,sizeof(GTextInfo));
2310 for ( cnt=0; nlnames[cnt]!=NULL; ++cnt) {
2311 namelistnames[cnt].text = (unichar_t *) nlnames[cnt];
2312 namelistnames[cnt].text_is_1byte = true;
2313 if ( strcmp(_((*(NameList **) (pl->val))->title),nlnames[cnt])==0 ) {
2314 namelistnames[cnt].selected = true;
2315 pgcd[gc].gd.label = &namelistnames[cnt];
2316 }
2317 }
2318 pgcd[gc].gd.u.list = namelistnames;
2319 pgcd[gc].creator = GListButtonCreate;
2320 pgcd[gc].gd.pos.width = 160;
2321 ++gc;
2322 hvarray[si++] = &pgcd[gc-1];
2323 hvarray[si++] = GCD_ColSpan; hvarray[si++] = GCD_ColSpan;
2324 y += 28;
2325 } break;
2326 case pr_string: case pr_file:
2327 if ( pl->set==SetAutoTraceArgs || ((char **) pl->val)==&mf_args )
2328 pgcd[gc].gd.pos.width = 160;
2329 if ( pl->val!=NULL )
2330 tempstr = *((char **) (pl->val));
2331 else
2332 tempstr = (char *) ((pl->get)());
2333 if ( tempstr!=NULL )
2334 plabel[gc].text = /* def2u_*/ uc_copy( tempstr );
2335 else if ( ((char **) pl->val)==&BDFFoundry )
2336 plabel[gc].text = /* def2u_*/ uc_copy( "FontForge" );
2337 else
2338 plabel[gc].text = /* def2u_*/ uc_copy( "" );
2339 plabel[gc].text_is_1byte = false;
2340 pgcd[gc++].creator = GTextFieldCreate;
2341 hvarray[si++] = &pgcd[gc-1];
2342 if ( pl->type==pr_file ) {
2343 pgcd[gc] = pgcd[gc-1];
2344 pgcd[gc-1].gd.pos.width = 140;
2345 hvarray[si++] = GCD_ColSpan;
2346 pgcd[gc].gd.pos.x += 145;
2347 pgcd[gc].gd.cid += CID_PrefsBrowseOffset;
2348 pgcd[gc].gd.label = &plabel[gc];
2349 plabel[gc].text = (unichar_t *) "...";
2350 plabel[gc].text_is_1byte = true;
2351 pgcd[gc].gd.handle_controlevent = Prefs_BrowseFile;
2352 pgcd[gc++].creator = GButtonCreate;
2353 hvarray[si++] = &pgcd[gc-1];
2354 } else if ( pl->set==SetAutoTraceArgs || ((char **) pl->val)==&mf_args ) {
2355 hvarray[si++] = GCD_ColSpan;
2356 hvarray[si++] = GCD_Glue;
2357 } else {
2358 hvarray[si++] = GCD_Glue;
2359 hvarray[si++] = GCD_Glue;
2360 }
2361 y += 26;
2362 if ( pl->val==NULL )
2363 free(tempstr);
2364 break;
2365 case pr_angle:
2366 sprintf(buf,"%g", *((float *) pl->val) * RAD2DEG);
2367 plabel[gc].text = (unichar_t *) copy( buf );
2368 pgcd[gc++].creator = GTextFieldCreate;
2369 hvarray[si++] = &pgcd[gc-1];
2370 plabel[gc].text = (unichar_t *) U_("°");
2371 plabel[gc].text_is_1byte = true;
2372 pgcd[gc].gd.label = &plabel[gc];
2373 pgcd[gc].gd.pos.x = pgcd[gc-1].gd.pos.x+gcd[gc-1].gd.pos.width+2; pgcd[gc].gd.pos.y = pgcd[gc-1].gd.pos.y;
2374 pgcd[gc].gd.flags = gg_enabled|gg_visible;
2375 pgcd[gc++].creator = GLabelCreate;
2376 hvarray[si++] = &pgcd[gc-1];
2377 hvarray[si++] = GCD_Glue;
2378 y += 26;
2379 break;
2380 }
2381 ++line;
2382 hvarray[si++] = NULL;
2383 }
2384 if ( visible_prefs_list[k].pl == args_list ) {
2385 static char *text[] = {
2386 /* GT: See the long comment at "Property|New" */
2387 /* GT: This and the next few strings show a limitation of my widget set which */
2388 /* GT: cannot handle multi-line text labels. These strings should be concatenated */
2389 /* GT: (after striping off "Prefs_App|") together, translated, and then broken up */
2390 /* GT: to fit the dialog. There is an extra blank line, not used in English, */
2391 /* GT: into which your text may extend if needed. */
2392 N_("Prefs_App|Normally FontForge will find applications by searching for"),
2393 N_("Prefs_App|them in your PATH environment variable, if you want"),
2394 N_("Prefs_App|to alter that behavior you may set an environment"),
2395 N_("Prefs_App|variable giving the full path spec of the application."),
2396 N_("Prefs_App|FontForge recognizes BROWSER, MF and AUTOTRACE."),
2397 N_("Prefs_App| "), /* A blank line */
2398 NULL };
2399 y += 8;
2400 for ( i=0; text[i]!=0; ++i ) {
2401 plabel[gc].text = (unichar_t *) S_(text[i]);
2402 plabel[gc].text_is_1byte = true;
2403 pgcd[gc].gd.label = &plabel[gc];
2404 pgcd[gc].gd.pos.x = 8;
2405 pgcd[gc].gd.pos.y = y;
2406 pgcd[gc].gd.flags = gg_visible | gg_enabled;
2407 pgcd[gc++].creator = GLabelCreate;
2408 hvarray[si++] = &pgcd[gc-1];
2409 hvarray[si++] = GCD_ColSpan; hvarray[si++] = GCD_ColSpan;
2410 hvarray[si++] = NULL;
2411 y += 12;
2412 }
2413 }
2414 if ( y>y2 ) y2 = y;
2415 hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
2416 hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
2417 hvarray[si++] = NULL;
2418 hvarray[si++] = NULL;
2419 boxes[2*k].gd.flags = gg_enabled|gg_visible;
2420 boxes[2*k].gd.u.boxelements = hvarray;
2421 boxes[2*k].creator = GHVBoxCreate;
2422 }
2423
2424 aspects[k].text = (unichar_t *) _("Script Menu");
2425 aspects[k].text_is_1byte = true;
2426 aspects[k++].gcd = sboxes;
2427
2428 subaspects[0].text = (unichar_t *) _("Features");
2429 subaspects[0].text_is_1byte = true;
2430 subaspects[0].gcd = mfboxes;
2431
2432 subaspects[1].text = (unichar_t *) _("Mapping");
2433 subaspects[1].text_is_1byte = true;
2434 subaspects[1].gcd = mpboxes;
2435
2436 mgcd[0].gd.pos.x = 4; gcd[0].gd.pos.y = 6;
2437 mgcd[0].gd.pos.width = GDrawPixelsToPoints(NULL,pos.width)-20;
2438 mgcd[0].gd.pos.height = y2;
2439 mgcd[0].gd.u.tabs = subaspects;
2440 mgcd[0].gd.flags = gg_visible | gg_enabled;
2441 mgcd[0].creator = GTabSetCreate;
2442
2443 aspects[k].text = (unichar_t *) _("Mac");
2444 aspects[k].text_is_1byte = true;
2445 aspects[k++].gcd = mgcd;
2446
2447 gc = 0;
2448
2449 gcd[gc].gd.pos.x = gcd[gc].gd.pos.y = 2;
2450 gcd[gc].gd.pos.width = pos.width-4; gcd[gc].gd.pos.height = pos.height-2;
2451 gcd[gc].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
2452 gcd[gc++].creator = GGroupCreate;
2453
2454 gcd[gc].gd.pos.x = 4; gcd[gc].gd.pos.y = 6;
2455 gcd[gc].gd.pos.width = GDrawPixelsToPoints(NULL,pos.width)-8;
2456 gcd[gc].gd.pos.height = y2+20+18+4;
2457 gcd[gc].gd.u.tabs = aspects;
2458 gcd[gc].gd.flags = gg_visible | gg_enabled | gg_tabset_vert;
2459 gcd[gc++].creator = GTabSetCreate;
2460 varray[0] = &gcd[gc-1]; varray[1] = NULL;
2461
2462 y = gcd[gc-1].gd.pos.y+gcd[gc-1].gd.pos.height;
2463
2464 gcd[gc].gd.pos.x = 30-3; gcd[gc].gd.pos.y = y+5-3;
2465 gcd[gc].gd.pos.width = -1; gcd[gc].gd.pos.height = 0;
2466 gcd[gc].gd.flags = gg_visible | gg_enabled | gg_but_default;
2467 label[gc].text = (unichar_t *) _("_OK");
2468 label[gc].text_is_1byte = true;
2469 label[gc].text_in_resource = true;
2470 gcd[gc].gd.mnemonic = 'O';
2471 gcd[gc].gd.label = &label[gc];
2472 gcd[gc].gd.handle_controlevent = Prefs_Ok;
2473 gcd[gc++].creator = GButtonCreate;
2474 harray[0] = GCD_Glue; harray[1] = &gcd[gc-1]; harray[2] = GCD_Glue; harray[3] = GCD_Glue;
2475
2476 gcd[gc].gd.pos.x = -30; gcd[gc].gd.pos.y = gcd[gc-1].gd.pos.y+3;
2477 gcd[gc].gd.pos.width = -1; gcd[gc].gd.pos.height = 0;
2478 gcd[gc].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
2479 label[gc].text = (unichar_t *) _("_Cancel");
2480 label[gc].text_is_1byte = true;
2481 label[gc].text_in_resource = true;
2482 gcd[gc].gd.label = &label[gc];
2483 gcd[gc].gd.mnemonic = 'C';
2484 gcd[gc].gd.handle_controlevent = Prefs_Cancel;
2485 gcd[gc++].creator = GButtonCreate;
2486 harray[4] = GCD_Glue; harray[5] = &gcd[gc-1]; harray[6] = GCD_Glue; harray[7] = NULL;
2487
2488 memset(mboxes,0,sizeof(mboxes));
2489 mboxes[2].gd.flags = gg_enabled|gg_visible;
2490 mboxes[2].gd.u.boxelements = harray;
2491 mboxes[2].creator = GHBoxCreate;
2492 varray[2] = &mboxes[2];
2493 varray[3] = NULL;
2494 varray[4] = NULL;
2495
2496 mboxes[0].gd.pos.x = mboxes[0].gd.pos.y = 2;
2497 mboxes[0].gd.flags = gg_enabled|gg_visible;
2498 mboxes[0].gd.u.boxelements = varray;
2499 mboxes[0].creator = GHVGroupCreate;
2500
2501 y = GDrawPointsToPixels(NULL,y+37);
2502 gcd[0].gd.pos.height = y-4;
2503
2504 GGadgetsCreate(gw,mboxes);
2505 GTextInfoListFree(mfgcd[0].gd.u.list);
2506 GTextInfoListFree(msgcd[0].gd.u.list);
2507
2508 GHVBoxSetExpandableRow(mboxes[0].ret,0);
2509 GHVBoxSetExpandableCol(mboxes[2].ret,gb_expandgluesame);
2510 GHVBoxSetExpandableRow(mfboxes[0].ret,0);
2511 GHVBoxSetExpandableCol(mfboxes[2].ret,gb_expandgluesame);
2512 GHVBoxSetExpandableRow(mpboxes[0].ret,0);
2513 GHVBoxSetExpandableCol(mpboxes[2].ret,gb_expandgluesame);
2514 GHVBoxSetExpandableRow(sboxes[0].ret,gb_expandglue);
2515 for ( k=0; k<TOPICS; ++k )
2516 GHVBoxSetExpandableRow(boxes[2*k].ret,gb_expandglue);
2517
2518 memset(&rq,0,sizeof(rq));
2519 rq.utf8_family_name = MONO_UI_FAMILIES;
2520 rq.point_size = 12;
2521 rq.weight = 400;
2522 font = GDrawInstanciateFont(gw,&rq);
2523 GGadgetSetFont(mfgcd[0].ret,font);
2524 GGadgetSetFont(msgcd[0].ret,font);
2525 GHVBoxFitWindow(mboxes[0].ret);
2526
2527 for ( k=0; visible_prefs_list[k].tab_name!=0; ++k ) for ( gc=0,i=0; visible_prefs_list[k].pl[i].name!=NULL; ++i ) {
2528 GGadgetCreateData *gcd = aspects[k].gcd[0].gd.u.boxelements[0];
2529 pl = &visible_prefs_list[k].pl[i];
2530 if ( pl->dontdisplay )
2531 continue;
2532 switch ( pl->type ) {
2533 case pr_bool:
2534 ++gc;
2535 break;
2536 case pr_encoding: {
2537 GGadget *g = gcd[gc+1].ret;
2538 list = GGadgetGetList(g,&llen);
2539 for ( j=0; j<llen ; ++j ) {
2540 if ( list[j]->text!=NULL &&
2541 (void *) (intpt) ( *((int *) pl->val)) == list[j]->userdata )
2542 list[j]->selected = true;
2543 else
2544 list[j]->selected = false;
2545 }
2546 if ( gcd[gc+1].gd.u.list!=encodingtypes )
2547 GTextInfoListFree(gcd[gc+1].gd.u.list);
2548 } break;
2549 case pr_namelist:
2550 free(gcd[gc+1].gd.u.list);
2551 break;
2552 case pr_string: case pr_file: case pr_int: case pr_real: case pr_unicode: case pr_angle:
2553 free(plabels[k][gc+1].text);
2554 if ( pl->type==pr_file || pl->type==pr_angle )
2555 ++gc;
2556 break;
2557 }
2558 gc += 2;
2559 }
2560
2561 for ( k=0; visible_prefs_list[k].tab_name!=0; ++k ) {
2562 free(aspects[k].gcd->gd.u.boxelements[0]);
2563 free(aspects[k].gcd->gd.u.boxelements);
2564 free(plabels[k]);
2565 }
2566
2567 GWidgetHidePalettes();
2568 GDrawSetVisible(gw,true);
2569 while ( !p.done )
2570 GDrawProcessOneEvent(NULL);
2571 GDrawDestroyWindow(gw);
2572 }
2573
RecentFilesRemember(char * filename)2574 void RecentFilesRemember(char *filename) {
2575 int i,j;
2576
2577 for ( i=0; i<RECENT_MAX && RecentFiles[i]!=NULL; ++i )
2578 if ( strcmp(RecentFiles[i],filename)==0 )
2579 break;
2580
2581 if ( i<RECENT_MAX && RecentFiles[i]!=NULL ) {
2582 if ( i!=0 ) {
2583 filename = RecentFiles[i];
2584 for ( j=i; j>0; --j )
2585 RecentFiles[j] = RecentFiles[j-1];
2586 RecentFiles[0] = filename;
2587 }
2588 } else {
2589 if ( RecentFiles[RECENT_MAX-1]!=NULL )
2590 free( RecentFiles[RECENT_MAX-1]);
2591 for ( i=RECENT_MAX-1; i>0; --i )
2592 RecentFiles[i] = RecentFiles[i-1];
2593 RecentFiles[0] = copy(filename);
2594 }
2595
2596 PrefsUI_SavePrefs(true);
2597 }
2598
LastFonts_Save(void)2599 void LastFonts_Save(void) {
2600 FontView *fv, *next;
2601 char buffer[1024];
2602 char *ffdir = getFontForgeUserDir(Config);
2603 FILE *preserve = NULL;
2604
2605 if ( ffdir ) {
2606 sprintf(buffer, "%s/FontsOpenAtLastQuit", ffdir);
2607 preserve = fopen(buffer,"w");
2608 free(ffdir);
2609 }
2610
2611 for ( fv = fv_list; fv!=NULL; fv = next ) {
2612 next = (FontView *) (fv->b.next);
2613 if ( preserve ) {
2614 SplineFont *sf = fv->b.cidmaster?fv->b.cidmaster:fv->b.sf;
2615 fprintf(preserve, "%s\n", sf->filename?sf->filename:sf->origname);
2616 }
2617 }
2618
2619 if ( preserve )
2620 fclose(preserve);
2621 }
2622
2623 struct prefs_interface gdraw_prefs_interface = {
2624 PrefsUI_SavePrefs,
2625 PrefsUI_LoadPrefs,
2626 PrefsUI_GetPrefs,
2627 PrefsUI_SetPrefs,
2628 PrefsUI_getFontForgeShareDir,
2629 PrefsUI_SetDefaults
2630 };
2631
change_res_filename(const char * newname)2632 static void change_res_filename(const char *newname) {
2633 free(xdefs_filename);
2634 xdefs_filename = copy( newname );
2635 SavePrefs(true);
2636 }
2637
DoXRes(void)2638 void DoXRes(void) {
2639 extern GResInfo fontview_ri;
2640
2641 MVColInit();
2642 CVColInit();
2643 BVColInit();
2644 GResEdit(&fontview_ri,xdefs_filename,change_res_filename);
2645 }
2646
2647 struct prefs_list pointer_dialog_list[] = {
2648 { N_("ArrowMoveSize"), pr_real, &arrowAmount, NULL, NULL, '\0', NULL, 0, N_("The number of em-units by which an arrow key will move a selected point") },
2649 { N_("ArrowAccelFactor"), pr_real, &arrowAccelFactor, NULL, NULL, '\0', NULL, 0, N_("Holding down the Shift key will speed up arrow key motion by this factor") },
2650 { N_("InterpolateCPsOnMotion"), pr_bool, &interpCPsOnMotion, NULL, NULL, '\0', NULL, 0, N_("When moving one end point of a spline but not the other\ninterpolate the control points between the two.") },
2651 PREFS_LIST_EMPTY
2652 };
2653
2654 struct prefs_list ruler_dialog_list[] = {
2655 { N_("SnapDistanceMeasureTool"), pr_real, &snapdistancemeasuretool, NULL, NULL, '\0', NULL, 0, N_("When the measure tool is active and when the mouse pointer is within this many pixels\nof one of the various interesting features (baseline,\nwidth, grid splines, etc.) the pointer will snap\nto that feature.") },
2656 { N_("MeasureToolShowHorizontalVertical"), pr_bool, &measuretoolshowhorizontolvertical, NULL, NULL, '\0', NULL, 0, N_("Have the measure tool show horizontal and vertical distances on the canvas.") },
2657 PREFS_LIST_EMPTY
2658 };
2659
PrefsSubSet_Ok(GGadget * g,GEvent * e)2660 static int PrefsSubSet_Ok(GGadget *g, GEvent *e) {
2661 GWindow gw = GGadgetGetWindow(g);
2662 struct pref_data *p = GDrawGetUserData(GGadgetGetWindow(g));
2663 struct prefs_list* plist = p->plist;
2664 struct prefs_list* pl = plist;
2665 int i=0,j=0;
2666 int err=0, enc;
2667 const unichar_t *ret;
2668
2669 p->done = true;
2670
2671 for ( i=0, pl=plist; pl->name; ++i, ++pl ) {
2672 switch( pl->type ) {
2673 case pr_int:
2674 *((int *) (pl->val)) = GetInt8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
2675 break;
2676 case pr_unicode:
2677 *((int *) (pl->val)) = GetUnicodeChar8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
2678 break;
2679 case pr_bool:
2680 *((int *) (pl->val)) = GGadgetIsChecked(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
2681 break;
2682 case pr_real:
2683 *((float *) (pl->val)) = GetReal8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err);
2684 break;
2685 case pr_encoding:
2686 { Encoding *e;
2687 e = ParseEncodingNameFromList(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
2688 if ( e!=NULL )
2689 *((Encoding **) (pl->val)) = e;
2690 enc = 1; /* So gcc doesn't complain about unused. It is unused, but why add the ifdef and make the code even messier? Sigh. icc complains anyway */
2691 }
2692 break;
2693 case pr_namelist:
2694 { NameList *nl;
2695 GTextInfo *ti = GGadgetGetListItemSelected(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
2696 if ( ti!=NULL ) {
2697 char *name = u2utf8_copy(ti->text);
2698 nl = NameListByName(name);
2699 free(name);
2700 if ( nl!=NULL && nl->uses_unicode && !allow_utf8_glyphnames)
2701 ff_post_error(_("Namelist contains non-ASCII names"),_("Glyph names should be limited to characters in the ASCII character set, but there are names in this namelist which use characters outside that range."));
2702 else if ( nl!=NULL )
2703 *((NameList **) (pl->val)) = nl;
2704 }
2705 }
2706 break;
2707 case pr_string: case pr_file:
2708 ret = _GGadgetGetTitle(GWidgetGetControl(gw,j*CID_PrefsOffset+CID_PrefsBase+i));
2709 if ( pl->val!=NULL ) {
2710 free( *((char **) (pl->val)) );
2711 *((char **) (pl->val)) = NULL;
2712 if ( ret!=NULL && *ret!='\0' )
2713 *((char **) (pl->val)) = /* u2def_*/ cu_copy(ret);
2714 } else {
2715 char *cret = cu_copy(ret);
2716 (pl->set)(cret);
2717 free(cret);
2718 }
2719 break;
2720 case pr_angle:
2721 *((float *) (pl->val)) = GetReal8(gw,j*CID_PrefsOffset+CID_PrefsBase+i,pl->name,&err)/RAD2DEG;
2722 break;
2723 }
2724 }
2725
2726 return( true );
2727 }
2728
PrefsSubSetDlg(CharView * cv,char * windowTitle,struct prefs_list * plist)2729 static void PrefsSubSetDlg(CharView *cv,char* windowTitle,struct prefs_list* plist) {
2730 struct prefs_list* pl = plist;
2731 GRect pos;
2732 GWindow gw;
2733 GWindowAttrs wattrs;
2734 GGadgetCreateData *pgcd, gcd[20], sgcd[45], mgcd[3], mfgcd[9], msgcd[9];
2735 GGadgetCreateData mfboxes[3], *mfarray[14];
2736 GGadgetCreateData mpboxes[3];
2737 GGadgetCreateData sboxes[2];
2738 GGadgetCreateData mboxes[3], mboxes2[5], *varray[5], *harray[8];
2739 GTextInfo *plabel, label[20], slabel[45], mflabels[9], mslabels[9];
2740 GTabInfo aspects[TOPICS+5], subaspects[3];
2741 GGadgetCreateData **hvarray, boxes[2*TOPICS];
2742 struct pref_data p;
2743 int line = 0,line_max = 3;
2744 int i = 0, gc = 0, ii, y=0, si=0, k=0;
2745 char buf[20];
2746 char *tempstr;
2747
2748 PrefsInit();
2749 MfArgsInit();
2750
2751 line_max=0;
2752 for ( i=0, pl=plist; pl->name; ++i, ++pl ) {
2753 ++line_max;
2754 }
2755
2756 int itemCount = 100;
2757 pgcd = calloc(itemCount,sizeof(GGadgetCreateData));
2758 plabel = calloc(itemCount,sizeof(GTextInfo));
2759 hvarray = calloc((itemCount)*5,sizeof(GGadgetCreateData *));
2760 memset(&p,'\0',sizeof(p));
2761 memset(&wattrs,0,sizeof(wattrs));
2762 memset(sgcd,0,sizeof(sgcd));
2763 memset(slabel,0,sizeof(slabel));
2764 memset(&mfgcd,0,sizeof(mfgcd));
2765 memset(&msgcd,0,sizeof(msgcd));
2766 memset(&mflabels,0,sizeof(mflabels));
2767 memset(&mslabels,0,sizeof(mslabels));
2768 memset(&mfboxes,0,sizeof(mfboxes));
2769 memset(&mpboxes,0,sizeof(mpboxes));
2770 memset(&sboxes,0,sizeof(sboxes));
2771 memset(&boxes,0,sizeof(boxes));
2772 memset(&mgcd,0,sizeof(mgcd));
2773 memset(&mgcd,0,sizeof(mgcd));
2774 memset(&subaspects,'\0',sizeof(subaspects));
2775 memset(&label,0,sizeof(label));
2776 memset(&gcd,0,sizeof(gcd));
2777 memset(&aspects,'\0',sizeof(aspects));
2778 GCDFillMacFeat(mfgcd,mflabels,250,default_mac_feature_map, true, mfboxes, mfarray);
2779
2780 p.plist = plist;
2781 wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
2782 wattrs.event_masks = ~(1<<et_charup);
2783 wattrs.restrict_input_to_me = 1;
2784 wattrs.is_dlg = 1;
2785 wattrs.undercursor = 1;
2786 wattrs.cursor = ct_pointer;
2787 wattrs.utf8_window_title = windowTitle;
2788 pos.x = pos.y = 0;
2789 pos.width = GGadgetScale(GDrawPointsToPixels(NULL,340));
2790 pos.height = GDrawPointsToPixels(NULL,line_max*26+25);
2791 gw = GDrawCreateTopWindow(NULL,&pos,e_h,&p,&wattrs);
2792
2793
2794
2795 for ( i=0, pl=plist; pl->name; ++i, ++pl ) {
2796
2797 plabel[gc].text = (unichar_t *) _(pl->name);
2798 plabel[gc].text_is_1byte = true;
2799 pgcd[gc].gd.label = &plabel[gc];
2800 pgcd[gc].gd.mnemonic = '\0';
2801 pgcd[gc].gd.popup_msg = 0;//_(pl->popup);
2802 pgcd[gc].gd.pos.x = 8;
2803 pgcd[gc].gd.pos.y = y + 6;
2804 pgcd[gc].gd.flags = gg_visible | gg_enabled;
2805 pgcd[gc++].creator = GLabelCreate;
2806 hvarray[si++] = &pgcd[gc-1];
2807
2808 plabel[gc].text_is_1byte = true;
2809 pgcd[gc].gd.label = &plabel[gc];
2810 pgcd[gc].gd.mnemonic = '\0';
2811 pgcd[gc].gd.popup_msg = 0;//_(pl->popup);
2812 pgcd[gc].gd.pos.x = 110;
2813 pgcd[gc].gd.pos.y = y;
2814 pgcd[gc].gd.flags = gg_visible | gg_enabled;
2815 pgcd[gc].data = pl;
2816 pgcd[gc].gd.cid = k*CID_PrefsOffset+CID_PrefsBase+i;
2817 switch ( pl->type ) {
2818 case pr_bool:
2819 plabel[gc].text = (unichar_t *) _("On");
2820 pgcd[gc].gd.pos.y += 3;
2821 pgcd[gc++].creator = GRadioCreate;
2822 hvarray[si++] = &pgcd[gc-1];
2823 pgcd[gc] = pgcd[gc-1];
2824 pgcd[gc].gd.pos.x += 50;
2825 pgcd[gc].gd.cid = 0;
2826 pgcd[gc].gd.label = &plabel[gc];
2827 plabel[gc].text = (unichar_t *) _("Off");
2828 plabel[gc].text_is_1byte = true;
2829 hvarray[si++] = &pgcd[gc];
2830 hvarray[si++] = GCD_Glue;
2831 if ( *((int *) pl->val))
2832 pgcd[gc-1].gd.flags |= gg_cb_on;
2833 else
2834 pgcd[gc].gd.flags |= gg_cb_on;
2835 ++gc;
2836 y += 22;
2837 break;
2838 case pr_int:
2839 sprintf(buf,"%d", *((int *) pl->val));
2840 plabel[gc].text = (unichar_t *) copy( buf );
2841 pgcd[gc++].creator = GTextFieldCreate;
2842 hvarray[si++] = &pgcd[gc-1];
2843 hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
2844 y += 26;
2845 break;
2846 case pr_unicode:
2847 /*sprintf(buf,"U+%04x", *((int *) pl->val));*/
2848 { char *pt; pt=buf; pt=utf8_idpb(pt,*((int *)pl->val),UTF8IDPB_NOZERO); *pt='\0'; }
2849 plabel[gc].text = (unichar_t *) copy( buf );
2850 pgcd[gc++].creator = GTextFieldCreate;
2851 hvarray[si++] = &pgcd[gc-1];
2852 hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
2853 y += 26;
2854 break;
2855 case pr_real:
2856 sprintf(buf,"%g", *((float *) pl->val));
2857 plabel[gc].text = (unichar_t *) copy( buf );
2858 pgcd[gc++].creator = GTextFieldCreate;
2859 hvarray[si++] = &pgcd[gc-1];
2860 hvarray[si++] = GCD_Glue; hvarray[si++] = GCD_Glue;
2861 y += 26;
2862 break;
2863 case pr_encoding:
2864 pgcd[gc].gd.u.list = GetEncodingTypes();
2865 pgcd[gc].gd.label = EncodingTypesFindEnc(pgcd[gc].gd.u.list,
2866 *(Encoding **) pl->val);
2867 for ( ii=0; pgcd[gc].gd.u.list[ii].text!=NULL ||pgcd[gc].gd.u.list[ii].line; ++ii )
2868 if ( pgcd[gc].gd.u.list[ii].userdata!=NULL &&
2869 (strcmp(pgcd[gc].gd.u.list[ii].userdata,"Compacted")==0 ||
2870 strcmp(pgcd[gc].gd.u.list[ii].userdata,"Original")==0 ))
2871 pgcd[gc].gd.u.list[ii].disabled = true;
2872 pgcd[gc].creator = GListFieldCreate;
2873 pgcd[gc].gd.pos.width = 160;
2874 if ( pgcd[gc].gd.label==NULL ) pgcd[gc].gd.label = &encodingtypes[0];
2875 ++gc;
2876 hvarray[si++] = &pgcd[gc-1];
2877 hvarray[si++] = GCD_ColSpan; hvarray[si++] = GCD_ColSpan;
2878 y += 28;
2879 break;
2880 case pr_namelist:
2881 { char **nlnames = AllNamelistNames();
2882 int cnt;
2883 GTextInfo *namelistnames;
2884 for ( cnt=0; nlnames[cnt]!=NULL; ++cnt);
2885 namelistnames = calloc(cnt+1,sizeof(GTextInfo));
2886 for ( cnt=0; nlnames[cnt]!=NULL; ++cnt) {
2887 namelistnames[cnt].text = (unichar_t *) nlnames[cnt];
2888 namelistnames[cnt].text_is_1byte = true;
2889 if ( strcmp(_((*(NameList **) (pl->val))->title),nlnames[cnt])==0 ) {
2890 namelistnames[cnt].selected = true;
2891 pgcd[gc].gd.label = &namelistnames[cnt];
2892 }
2893 }
2894 pgcd[gc].gd.u.list = namelistnames;
2895 pgcd[gc].creator = GListButtonCreate;
2896 pgcd[gc].gd.pos.width = 160;
2897 ++gc;
2898 hvarray[si++] = &pgcd[gc-1];
2899 hvarray[si++] = GCD_ColSpan; hvarray[si++] = GCD_ColSpan;
2900 y += 28;
2901 } break;
2902 case pr_string: case pr_file:
2903 if ( pl->set==SetAutoTraceArgs || ((char **) pl->val)==&mf_args )
2904 pgcd[gc].gd.pos.width = 160;
2905 if ( pl->val!=NULL )
2906 tempstr = *((char **) (pl->val));
2907 else
2908 tempstr = (char *) ((pl->get)());
2909 if ( tempstr!=NULL )
2910 plabel[gc].text = /* def2u_*/ uc_copy( tempstr );
2911 else if ( ((char **) pl->val)==&BDFFoundry )
2912 plabel[gc].text = /* def2u_*/ uc_copy( "FontForge" );
2913 else
2914 plabel[gc].text = /* def2u_*/ uc_copy( "" );
2915 plabel[gc].text_is_1byte = false;
2916 pgcd[gc++].creator = GTextFieldCreate;
2917 hvarray[si++] = &pgcd[gc-1];
2918 if ( pl->type==pr_file ) {
2919 pgcd[gc] = pgcd[gc-1];
2920 pgcd[gc-1].gd.pos.width = 140;
2921 hvarray[si++] = GCD_ColSpan;
2922 pgcd[gc].gd.pos.x += 145;
2923 pgcd[gc].gd.cid += CID_PrefsBrowseOffset;
2924 pgcd[gc].gd.label = &plabel[gc];
2925 plabel[gc].text = (unichar_t *) "...";
2926 plabel[gc].text_is_1byte = true;
2927 pgcd[gc].gd.handle_controlevent = Prefs_BrowseFile;
2928 pgcd[gc++].creator = GButtonCreate;
2929 hvarray[si++] = &pgcd[gc-1];
2930 } else if ( pl->set==SetAutoTraceArgs || ((char **) pl->val)==&mf_args ) {
2931 hvarray[si++] = GCD_ColSpan;
2932 hvarray[si++] = GCD_Glue;
2933 } else {
2934 hvarray[si++] = GCD_Glue;
2935 hvarray[si++] = GCD_Glue;
2936 }
2937 y += 26;
2938 if ( pl->val==NULL )
2939 free(tempstr);
2940 break;
2941 case pr_angle:
2942 sprintf(buf,"%g", *((float *) pl->val) * RAD2DEG);
2943 plabel[gc].text = (unichar_t *) copy( buf );
2944 pgcd[gc++].creator = GTextFieldCreate;
2945 hvarray[si++] = &pgcd[gc-1];
2946 plabel[gc].text = (unichar_t *) U_("°");
2947 plabel[gc].text_is_1byte = true;
2948 pgcd[gc].gd.label = &plabel[gc];
2949 pgcd[gc].gd.pos.x = pgcd[gc-1].gd.pos.x+gcd[gc-1].gd.pos.width+2; pgcd[gc].gd.pos.y = pgcd[gc-1].gd.pos.y;
2950 pgcd[gc].gd.flags = gg_enabled|gg_visible;
2951 pgcd[gc++].creator = GLabelCreate;
2952 hvarray[si++] = &pgcd[gc-1];
2953 hvarray[si++] = GCD_Glue;
2954 y += 26;
2955 break;
2956 }
2957 ++line;
2958 hvarray[si++] = NULL;
2959
2960 }
2961
2962 harray[4] = 0;
2963 harray[5] = 0;
2964 harray[6] = 0;
2965 harray[7] = 0;
2966
2967 gcd[gc].gd.pos.x = 30-3;
2968 gcd[gc].gd.pos.y = y+5-3;
2969 gcd[gc].gd.pos.width = -1;
2970 gcd[gc].gd.pos.height = 0;
2971 gcd[gc].gd.flags = gg_visible | gg_enabled | gg_but_default;
2972 label[gc].text = (unichar_t *) _("_OK");
2973 label[gc].text_is_1byte = true;
2974 label[gc].text_in_resource = true;
2975 gcd[gc].gd.mnemonic = 'O';
2976 gcd[gc].gd.label = &label[gc];
2977 gcd[gc].gd.handle_controlevent = PrefsSubSet_Ok;
2978 gcd[gc++].creator = GButtonCreate;
2979 harray[0] = GCD_Glue; harray[1] = &gcd[gc-1]; harray[2] = GCD_Glue; harray[3] = GCD_Glue;
2980
2981
2982 memset(mboxes,0,sizeof(mboxes));
2983 memset(mboxes2,0,sizeof(mboxes2));
2984
2985 mboxes[2].gd.pos.x = 2;
2986 mboxes[2].gd.pos.y = 20;
2987 mboxes[2].gd.flags = gg_enabled|gg_visible;
2988 mboxes[2].gd.u.boxelements = harray;
2989 mboxes[2].creator = GHBoxCreate;
2990
2991 mboxes[0].gd.pos.x = mboxes[0].gd.pos.y = 2;
2992 mboxes[0].gd.flags = gg_enabled|gg_visible;
2993 mboxes[0].gd.u.boxelements = hvarray;
2994 mboxes[0].creator = GHVGroupCreate;
2995
2996 varray[0] = &mboxes[0];
2997 varray[1] = &mboxes[2];
2998 varray[2] = 0;
2999 varray[3] = 0;
3000 varray[4] = 0;
3001
3002 /* varray[0] = &mboxes[2]; */
3003 /* varray[1] = 0;//&mboxes[2]; */
3004 /* varray[2] = 0; */
3005 /* varray[3] = 0; */
3006 /* varray[4] = 0; */
3007
3008 mboxes2[0].gd.pos.x = 4;
3009 mboxes2[0].gd.pos.y = 4;
3010 mboxes2[0].gd.flags = gg_enabled|gg_visible;
3011 mboxes2[0].gd.u.boxelements = varray;
3012 mboxes2[0].creator = GVBoxCreate;
3013
3014 GGadgetsCreate(gw,mboxes2);
3015
3016
3017 GDrawSetVisible(gw,true);
3018 while ( !p.done )
3019 GDrawProcessOneEvent(NULL);
3020 GDrawDestroyWindow(gw);
3021 }
3022
3023
PointerDlg(CharView * cv)3024 void PointerDlg(CharView *cv) {
3025 PrefsSubSetDlg( cv, _("Arrow Options"), pointer_dialog_list );
3026 }
3027
RulerDlg(CharView * cv)3028 void RulerDlg(CharView *cv) {
3029 PrefsSubSetDlg( cv, _("Ruler Options"), ruler_dialog_list );
3030 }
3031
3032