Skip to content
Permalink
Browse files Browse the repository at this point in the history
Warn users before discarding their unsaved scripts (#3852)
* Warn users before discarding their unsaved scripts

This closes #3846.
  • Loading branch information
ctrlcctrlv committed Aug 13, 2019
1 parent e6b9b0f commit 626f751
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 1 deletion.
1 change: 1 addition & 0 deletions fontforge/views.h
Expand Up @@ -476,6 +476,7 @@ typedef struct fontview {
struct lookup_subtable *cur_subtable;
struct qg_data *qg;
GPid pid_webfontserver;
bool script_unsaved; // Whether or not there's an unsaved script in script dialog
} FontView;

typedef struct findsel {
Expand Down
20 changes: 20 additions & 0 deletions fontforgeexe/fontview.c
Expand Up @@ -80,6 +80,7 @@ char *script_filenames[SCRIPT_MENU_MAX];
extern int onlycopydisplayed, copymetadata, copyttfinstr, add_char_to_name_list;
int home_char='A';
int compact_font_on_open=0;
bool warn_script_unsaved = true;
int navigation_mask = 0; /* Initialized in startui.c */

static char *fv_fontnames = MONO_UI_FAMILIES;
Expand Down Expand Up @@ -534,6 +535,22 @@ static int AskChanged(SplineFont *sf) {
return( ret );
}

static int AskScriptChanged() {
int ret;
char *buts[4];

buts[0] = _("_Yes");
buts[1] = _("Yes, and don't _remind me again");
buts[2] = _("_No");
buts[3] = NULL;
ret = gwwv_ask( _("Unsaved script"),(const char **) buts,0,2,_("You have an unsaved script in the «Execute Script» dialog. Do you intend to discard it?"));
if (ret == 1) {
warn_script_unsaved = false;
SavePrefs(true);
}
return( ret );
}

int _FVMenuGenerate(FontView *fv,int family) {
FVFlattenAllBitmapSelections(fv);
return( SFGenerateFont(fv->b.sf,fv->b.active_layer,family,fv->b.normal==NULL?fv->b.map:fv->b.normal) );
Expand Down Expand Up @@ -858,6 +875,9 @@ return( false );

if ( fv->b.nextsame!=NULL || fv->b.sf->fv!=&fv->b ) {
/* There's another view, can close this one with no problems */
} else if ( warn_script_unsaved && fv->script_unsaved &&
AskScriptChanged()==2 ) {
return false;
} else if ( SFAnyChanged(sf) ) {
i = AskChanged(fv->b.sf);
if ( i==2 ) /* Cancel */
Expand Down
2 changes: 2 additions & 0 deletions fontforgeexe/prefs.c
Expand Up @@ -194,6 +194,7 @@ extern int prefs_cv_outline_thickness; /* from charview.c */

extern float OpenTypeLoadHintEqualityTolerance; /* autohint.c */
extern float GenerateHintWidthEqualityTolerance; /* splinesave.c */
extern bool warn_script_unsaved; /* fontview.c */
extern NameList *force_names_when_opening;
extern NameList *force_names_when_saving;
extern NameList *namelist_for_new_fonts;
Expand Down Expand Up @@ -311,6 +312,7 @@ static struct prefs_list {
{ 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.") },
{ 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.") },
{ 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.") },
{ 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.") },
PREFS_LIST_EMPTY
},
new_list[] = {
Expand Down
4 changes: 4 additions & 0 deletions fontforgeexe/scriptingdlg.c
Expand Up @@ -189,6 +189,10 @@ return( true );

if ( event->type==et_close ) {
SD_DoCancel( sd );
} else if ( event->type==et_controlevent && event->u.control.subtype==et_textchanged ) {
sd->fv->script_unsaved = !GTextFieldIsEmpty(GWidgetGetControl(sd->gw,CID_Script));
} else if ( event->type==et_controlevent && event->u.control.subtype==et_save ) {
sd->fv->script_unsaved = false;
} else if ( event->type==et_char ) {
if ( event->u.chr.keysym == GK_F1 || event->u.chr.keysym == GK_Help ) {
help("scripting.html");
Expand Down
19 changes: 19 additions & 0 deletions gdraw/gtextfield.c
Expand Up @@ -215,6 +215,19 @@ static void GTextFieldChanged(GTextField *gt,int src) {
GDrawPostEvent(&e);
}

static void GTextFieldSaved(GTextField *gt) {
GEvent e;

e.type = et_controlevent;
e.w = gt->g.base;
e.u.control.subtype = et_save;
e.u.control.g = &gt->g;
if ( gt->g.handle_controlevent != NULL )
(gt->g.handle_controlevent)(&gt->g,&e);
else
GDrawPostEvent(&e);
}

static void GTextFieldFocusChanged(GTextField *gt,int gained) {
GEvent e;

Expand Down Expand Up @@ -878,6 +891,11 @@ static unichar_t txt[] = { '*','.','{','t','x','t',',','p','y','}', '\0' };
static unichar_t errort[] = { 'C','o','u','l','d',' ','n','o','t',' ','o','p','e','n', '\0' };
static unichar_t error[] = { 'C','o','u','l','d',' ','n','o','t',' ','o','p','e','n',' ','%','.','1','0','0','h','s', '\0' };

bool GTextFieldIsEmpty(GGadget *g) {
GTextField *gt = (GTextField *) g;
return gt->text == NULL || *gt->text == '\0';
}

static void GTextFieldImport(GTextField *gt) {
unichar_t *ret;
char *cret;
Expand Down Expand Up @@ -970,6 +988,7 @@ return;
}
}
fclose(file);
GTextFieldSaved(gt);
}

#define MID_Cut 1
Expand Down
2 changes: 1 addition & 1 deletion inc/gdraw.h
Expand Up @@ -120,7 +120,7 @@ enum et_subtype { et_buttonpress, et_buttonactivate, et_radiochanged,
et_listselected, et_listdoubleclick,
et_scrollbarchange,
et_textchanged, et_textfocuschanged,
et_lastsubtype };
et_save, et_lastsubtype };

enum sb { et_sb_top, et_sb_uppage, et_sb_up, et_sb_left=et_sb_up,
et_sb_down, et_sb_right=et_sb_down, et_sb_downpage,
Expand Down
1 change: 1 addition & 0 deletions inc/ggadget.h
Expand Up @@ -406,6 +406,7 @@ GGadgetHandler GGadgetGetHandler(GGadget *g);
void GTextFieldSelect(GGadget *g,int sel_start, int sel_end);
void GTextFieldShow(GGadget *g,int pos);
void GTextFieldReplace(GGadget *g,const unichar_t *txt);
bool GTextFieldIsEmpty(GGadget *g);
void GCompletionFieldSetCompletion(GGadget *g,GTextCompletionHandler completion);
void GCompletionFieldSetCompletionMode(GGadget *g,int enabled);
void GGadgetClearList(GGadget *g);
Expand Down

0 comments on commit 626f751

Please sign in to comment.