AnalogTerm2: Fix a bug in select_end()
authorMatthew Mondor <mmondor@pulsar-zone.net>
Mon, 25 Sep 2023 09:51:28 +0000 (09:51 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Mon, 25 Sep 2023 09:51:28 +0000 (09:51 +0000)
A crash was occasionally possible since the introduction of the
selection expiry timer, a type of race condition.  Add extra -1
checks and reset the timer for related X11 events.

mmsoftware/analogterm2/src/screen.c

index 676ffba..c235f8c 100644 (file)
@@ -142,7 +142,8 @@ static Time         lastmotion = -1;
 static Atom            atom_primary, atom_targets, atom_utf8_string,
                        atom_string, atom_incr;
 
-int                    screen_select_ticks = 0;
+int                    screen_select_ticks = 0,
+                       screen_select_ticks_reset = 0;
 bool                   screen_select_clear_now = false;
 
 
@@ -294,6 +295,13 @@ screen_init(void)
        atom_string = XInternAtom(s->dpy, "STRING", False);
        atom_incr = XInternAtom(s->dpy, "INCR", False);
 
+       /* Number of ticks to reset selection expiry timer. */
+       if (cfg_selecttimeout > 0)
+               screen_select_ticks_reset = cfg_selecttimeout *
+                   (1000000 / cfg_refreshspeed);
+       else
+               screen_select_ticks_reset = 0;
+
        s->focus = true;
 
        return s;
@@ -716,6 +724,8 @@ void
 screen_select_start(state_t *st, XButtonEvent *bev)
 {
 
+       screen_select_ticks = screen_select_ticks_reset;
+
        if (bev->button != 1)
                return;
 
@@ -734,13 +744,16 @@ screen_select_end(state_t *st, XButtonEvent *bev)
        size_t bufsize;
        int x, y;
 
+       screen_select_ticks = screen_select_ticks_reset;
+
        if (bev->button != 1)
                return;
        if (!st->selecting)
                return;
 
        st->selecting = false;
-       if (st->sel_x2 == -1 || st->sel_y2 == -1)
+       if (st->sel_x1 == -1 || st->sel_y1 == -1 ||
+           st->sel_x2 == -1 || st->sel_y2 == -1)
                return;
 
        /* Free any previous selection */
@@ -821,17 +834,14 @@ done:
        if (st->selected)
                XSetSelectionOwner(screen->dpy, atom_primary, screen->win,
                    CurrentTime);
-
-       /* Set expiry */
-       if (cfg_selecttimeout > 0)
-               screen_select_ticks = cfg_selecttimeout *
-                   (1000000 / cfg_refreshspeed);
 }
 
 void
 screen_select_adjust(state_t *st, XMotionEvent *mev)
 {
 
+       screen_select_ticks = screen_select_ticks_reset;
+
        if ((mev->state & Button1Mask) == 0)
                return;
        if (!st->selecting)
@@ -862,6 +872,8 @@ void
 screen_select_paste(state_t *st, XButtonEvent *bev)
 {
 
+       screen_select_ticks = screen_select_ticks_reset;
+
        if (bev->button != 2)
                return;
        if (st->pasting != None)