diff options
Diffstat (limited to 'src/display.c')
-rw-r--r-- | src/display.c | 1429 |
1 files changed, 245 insertions, 1184 deletions
diff --git a/src/display.c b/src/display.c index 3e0bdae..5fc5f4b 100644 --- a/src/display.c +++ b/src/display.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008 +/* Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) @@ -37,12 +37,12 @@ #include "screen.h" #include "extern.h" #include "braille.h" +#include "canvas.h" static int CountChars __P((int)); static int DoAddChar __P((int)); static int BlankResize __P((int, int)); static int CallRewrite __P((int, int, int, int)); -static void FreeCanvas __P((struct canvas *)); static void disp_readev_fn __P((struct event *, char *)); static void disp_writeev_fn __P((struct event *, char *)); #ifdef linux @@ -65,8 +65,7 @@ static void RAW_PUTCHAR __P((int)); #ifdef COLOR static void SetBackColor __P((int)); #endif -static void FreePerp __P((struct canvas *)); -static struct canvas *AddPerp __P((struct canvas *)); +static void RemoveStatusMinWait __P((void)); extern struct layer *flayer; @@ -122,6 +121,7 @@ struct display TheDisplay; */ int defobuflimit = OBUF_MAX; int defnonblock = -1; +int defmousetrack = 0; #ifdef AUTO_NUKE int defautonuke = 0; #endif @@ -200,7 +200,8 @@ struct LayFuncs BlankLf = DefClearLine, DefRewrite, BlankResize, - DefRestore + DefRestore, + 0 }; /*ARGSUSED*/ @@ -313,6 +314,7 @@ struct mode *Mode; D_termname[sizeof(D_termname) - 1] = 0; D_user = *u; D_processinput = ProcessInput; + D_mousetrack = defmousetrack; return display; } @@ -333,7 +335,7 @@ FreeDisplay() #endif if (D_userfd >= 0) { - Flush(); + Flush(3); if (!display) return; SetTTY(D_userfd, &D_OldMode); @@ -411,738 +413,17 @@ FreeDisplay() if (p->w_zdisplay == display) zmodem_abort(p, 0); #endif + if (D_mousetrack) + { + D_mousetrack = 0; + MouseMode(0); + } #ifdef MULTI free((char *)display); #endif display = 0; } -static void -CanvasInitBlank(cv) -struct canvas *cv; -{ - cv->c_blank.l_cvlist = cv; - cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1; - cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; - cv->c_blank.l_x = cv->c_blank.l_y = 0; - cv->c_blank.l_layfn = &BlankLf; - cv->c_blank.l_data = 0; - cv->c_blank.l_next = 0; - cv->c_blank.l_bottom = &cv->c_blank; - cv->c_blank.l_blocking = 0; - cv->c_layer = &cv->c_blank; -} - -int -MakeDefaultCanvas() -{ - struct canvas *cv; - - ASSERT(display); - if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0) - return -1; - cv->c_xs = 0; - cv->c_xe = D_width - 1; - cv->c_ys = 0; - cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways; - debug2("MakeDefaultCanvas 0,0 %d,%d\n", cv->c_xe, cv->c_ye); - cv->c_xoff = 0; - cv->c_yoff = 0; - cv->c_next = 0; - cv->c_display = display; - cv->c_vplist = 0; - cv->c_slnext = 0; - cv->c_slprev = 0; - cv->c_slperp = 0; - cv->c_slweight = 1; - cv->c_slback = &D_canvas; - D_canvas.c_slperp = cv; - D_canvas.c_xs = cv->c_xs; - D_canvas.c_xe = cv->c_xe; - D_canvas.c_ys = cv->c_ys; - D_canvas.c_ye = cv->c_ye; - cv->c_slorient = SLICE_UNKN; - cv->c_captev.type = EV_TIMEOUT; - cv->c_captev.data = (char *)cv; - cv->c_captev.handler = cv_winid_fn; - - CanvasInitBlank(cv); - cv->c_lnext = 0; - - D_cvlist = cv; - RethinkDisplayViewports(); - D_forecv = cv; /* default input focus */ - return 0; -} - -static struct canvas ** -CreateCanvasChainRec(cv, cvp) -struct canvas *cv; -struct canvas **cvp; -{ - for (; cv; cv = cv->c_slnext) - { - if (cv->c_slperp) - cvp = CreateCanvasChainRec(cv->c_slperp, cvp); - else - { - *cvp = cv; - cvp = &cv->c_next; - } - } - return cvp; -} - -void -RecreateCanvasChain() -{ - struct canvas **cvp; - cvp = CreateCanvasChainRec(D_canvas.c_slperp, &D_cvlist); - *cvp = 0; -} - -static void -FreeCanvas(cv) -struct canvas *cv; -{ - struct viewport *vp, *nvp; - struct canvas **cvp; - struct win *p; - - if (cv->c_slprev) - cv->c_slprev->c_slnext = cv->c_slnext; - if (cv->c_slnext) - cv->c_slnext->c_slprev = cv->c_slprev; - if (cv->c_slback && cv->c_slback->c_slperp == cv) - cv->c_slback->c_slperp = cv->c_slnext ? cv->c_slnext : cv->c_slprev; - if (cv->c_slperp) - { - while (cv->c_slperp) - FreeCanvas(cv->c_slperp); - free(cv); - return; - } - - if (display) - { - if (D_forecv == cv) - D_forecv = 0; - /* remove from canvas chain as SetCanvasWindow might call - * some layer function */ - for (cvp = &D_cvlist; *cvp ; cvp = &(*cvp)->c_next) - if (*cvp == cv) - { - *cvp = cv->c_next; - break; - } - } - p = cv->c_layer ? Layer2Window(cv->c_layer) : 0; - SetCanvasWindow(cv, 0); - if (p) - WindowChanged(p, 'u'); - if (flayer == cv->c_layer) - flayer = 0; - for (vp = cv->c_vplist; vp; vp = nvp) - { - vp->v_canvas = 0; - nvp = vp->v_next; - vp->v_next = 0; - free(vp); - } - evdeq(&cv->c_captev); - free(cv); -} - -int -CountCanvas(cv) -struct canvas *cv; -{ - int num = 0; - for (; cv; cv = cv->c_slnext) - { - if (cv->c_slperp) - { - struct canvas *cvp; - int nump = 1, n; - for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext) - if (cvp->c_slperp) - { - n = CountCanvas(cvp->c_slperp); - if (n > nump) - nump = n; - } - num += nump; - } - else - num++; - } - return num; -} - -int -CountCanvasPerp(cv) -struct canvas *cv; -{ - struct canvas *cvp; - int num = 1, n; - for (cvp = cv->c_slperp; cvp; cvp = cvp->c_slnext) - if (cvp->c_slperp) - { - n = CountCanvas(cvp->c_slperp); - if (n > num) - num = n; - } - return num; -} - -void -EqualizeCanvas(cv, gflag) -struct canvas *cv; -int gflag; -{ - struct canvas *cv2; - for (; cv; cv = cv->c_slnext) - { - if (cv->c_slperp && gflag) - { - cv->c_slweight = CountCanvasPerp(cv); - for (cv2 = cv->c_slperp; cv2; cv2 = cv2->c_slnext) - if (cv2->c_slperp) - EqualizeCanvas(cv2->c_slperp, gflag); - } - else - cv->c_slweight = 1; - } -} - -void -ResizeCanvas(cv) -struct canvas *cv; -{ - struct canvas *cv2, *cvn, *fcv; - int nh, i, maxi, hh, m, w, wsum; - int need, got; - int xs, ys, xe, ye; - int focusmin = 0; - - xs = cv->c_xs; - ys = cv->c_ys; - xe = cv->c_xe; - ye = cv->c_ye; - cv = cv->c_slperp; - debug2("ResizeCanvas: %d,%d", xs, ys); - debug2(" %d,%d\n", xe, ye); - if (cv == 0) - return; - if (cv->c_slorient == SLICE_UNKN) - { - ASSERT(!cv->c_slnext && !cv->c_slperp); - cv->c_xs = xs; - cv->c_xe = xe; - cv->c_ys = ys; - cv->c_ye = ye; - cv->c_xoff = cv->c_xs; - cv->c_yoff = cv->c_ys; - cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1; - cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; - return; - } - - fcv = 0; - if (focusminwidth || focusminheight) - { - debug("searching for focus canvas\n"); - cv2 = D_forecv; - while (cv2->c_slback) - { - if (cv2->c_slback == cv->c_slback) - { - fcv = cv2; - focusmin = cv->c_slorient == SLICE_VERT ? focusminheight : focusminwidth; - if (focusmin > 0) - focusmin--; - else if (focusmin < 0) - focusmin = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2; - debug1("found, focusmin=%d\n", focusmin); - } - cv2 = cv2->c_slback; - } - } - if (focusmin) - { - m = CountCanvas(cv) * 2; - nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2; - nh -= m; - if (nh < 0) - nh = 0; - if (focusmin > nh) - focusmin = nh; - debug1("corrected to %d\n", focusmin); - } - - /* pass 1: calculate weight sum */ - for (cv2 = cv, wsum = 0; cv2; cv2 = cv2->c_slnext) - { - debug1(" weight %d\n", cv2->c_slweight); - wsum += cv2->c_slweight; - } - debug1("wsum = %d\n", wsum); - if (wsum == 0) - wsum = 1; - w = wsum; - - /* pass 2: calculate need/excess space */ - nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2; - for (cv2 = cv, need = got = 0; cv2; cv2 = cv2->c_slnext) - { - m = cv2->c_slperp ? CountCanvasPerp(cv2) * 2 - 1 : 1; - if (cv2 == fcv) - m += focusmin; - hh = cv2->c_slweight ? nh * cv2->c_slweight / w : 0; - w -= cv2->c_slweight; - nh -= hh; - debug2(" should %d min %d\n", hh, m); - if (hh <= m + 1) - need += m + 1 - hh; - else - got += hh - m - 1; - } - debug2("need: %d, got %d\n", need, got); - if (need > got) - need = got; - - /* pass 3: distribute space */ - nh = cv->c_slorient == SLICE_VERT ? ye - ys + 2 : xe - xs + 2; - i = cv->c_slorient == SLICE_VERT ? ys : xs; - maxi = cv->c_slorient == SLICE_VERT ? ye : xe; - w = wsum; - for (; cv; cv = cvn) - { - cvn = cv->c_slnext; - if (i > maxi) - { - if (cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slprev->c_slperp && !cv->c_slprev->c_slprev) - { - cv->c_slprev->c_slorient = SLICE_UNKN; - if (!captionalways) - { - cv->c_slback->c_ye++; - cv->c_slprev->c_ye++; - } - } - SetCanvasWindow(cv, 0); - FreeCanvas(cv); - continue; - } - m = cv->c_slperp ? CountCanvasPerp(cv) * 2 - 1 : 1; - if (cv == fcv) - m += focusmin; - hh = cv->c_slweight ? nh * cv->c_slweight / w : 0; - w -= cv->c_slweight; - nh -= hh; - debug2(" should %d min %d\n", hh, m); - if (hh <= m + 1) - { - hh = m + 1; - debug1(" -> %d\n", hh); - } - else - { - int hx = need * (hh - m - 1) / got; - debug3(" -> %d - %d = %d\n", hh, hx, hh - hx); - got -= (hh - m - 1); - hh -= hx; - need -= hx; - debug2(" now need=%d got=%d\n", need, got); - } - ASSERT(hh >= m + 1); - /* hh is window size plus pation line */ - if (i + hh > maxi + 2) - { - hh = maxi + 2 - i; - debug1(" not enough space, reducing to %d\n", hh); - } - if (i + hh == maxi + 1) - { - hh++; - debug(" incrementing as no other canvas will fit\n"); - } - if (cv->c_slorient == SLICE_VERT) - { - cv->c_xs = xs; - cv->c_xe = xe; - cv->c_ys = i; - cv->c_ye = i + hh - 2; - cv->c_xoff = xs; - cv->c_yoff = i; - } - else - { - cv->c_xs = i; - cv->c_xe = i + hh - 2; - cv->c_ys = ys; - cv->c_ye = ye; - cv->c_xoff = i; - cv->c_yoff = ys; - } - cv->c_xoff = cv->c_xs; - cv->c_yoff = cv->c_ys; - cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1; - cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; - if (cv->c_slperp) - { - ResizeCanvas(cv); - if (!cv->c_slperp->c_slnext) - { - debug("deleting perp node\n"); - FreePerp(cv->c_slperp); - FreePerp(cv); - } - } - i += hh; - } -} - -static struct canvas * -AddPerp(cv) -struct canvas *cv; -{ - struct canvas *pcv; - debug("Creating new perp node\n"); - - if ((pcv = (struct canvas *)calloc(1, sizeof *cv)) == 0) - return 0; - pcv->c_next = 0; - pcv->c_display = cv->c_display; - pcv->c_slnext = cv->c_slnext; - pcv->c_slprev = cv->c_slprev; - pcv->c_slperp = cv; - pcv->c_slback = cv->c_slback; - if (cv->c_slback && cv->c_slback->c_slperp == cv) - cv->c_slback->c_slperp = pcv; - pcv->c_slorient = cv->c_slorient; - pcv->c_xoff = 0; - pcv->c_yoff = 0; - pcv->c_xs = cv->c_xs; - pcv->c_xe = cv->c_xe; - pcv->c_ys = cv->c_ys; - pcv->c_ye = cv->c_ye; - if (pcv->c_slnext) - pcv->c_slnext->c_slprev = pcv; - if (pcv->c_slprev) - pcv->c_slprev->c_slnext = pcv; - pcv->c_slweight = cv->c_slweight; - CanvasInitBlank(pcv); - cv->c_slweight = 1; - cv->c_slnext = 0; - cv->c_slprev = 0; - cv->c_slperp = 0; - cv->c_slback = pcv; - cv->c_slorient = SLICE_UNKN; - return pcv; -} - -static void -FreePerp(pcv) -struct canvas *pcv; -{ - struct canvas *cv; - - if (!pcv->c_slperp) - return; - cv = pcv->c_slperp; - cv->c_slprev = pcv->c_slprev; - if (cv->c_slprev) - cv->c_slprev->c_slnext = cv; - cv->c_slback = pcv->c_slback; - if (cv->c_slback && cv->c_slback->c_slperp == pcv) - cv->c_slback->c_slperp = cv; - cv->c_slorient = pcv->c_slorient; - cv->c_slweight = pcv->c_slweight; - while (cv->c_slnext) - { - cv = cv->c_slnext; - cv->c_slorient = pcv->c_slorient; - cv->c_slback = pcv->c_slback; - cv->c_slweight = pcv->c_slweight; - } - cv->c_slnext = pcv->c_slnext; - if (cv->c_slnext) - cv->c_slnext->c_slprev = cv; - free(pcv); -} - -int -AddCanvas(orient) -int orient; -{ - struct canvas *cv; - int xs, xe, ys, ye; - int h, num; - - cv = D_forecv; - debug2("AddCanvas orient %d, forecv is %d\n", orient, cv->c_slorient); - - if (cv->c_slorient != SLICE_UNKN && cv->c_slorient != orient) - if (!AddPerp(cv)) - return -1; - - cv = D_forecv; - xs = cv->c_slback->c_xs; - xe = cv->c_slback->c_xe; - ys = cv->c_slback->c_ys; - ye = cv->c_slback->c_ye; - if (!captionalways && cv == D_canvas.c_slperp && !cv->c_slnext) - ye--; /* need space for caption */ - debug2("Adding Canvas to slice %d,%d ", xs, ys); - debug2("%d,%d\n", xe, ye); - - num = CountCanvas(cv->c_slback->c_slperp) + 1; - debug1("Num = %d\n", num); - if (orient == SLICE_VERT) - h = ye - ys + 1; - else - h = xe - xs + 1; - - h -= 2 * num - 1; - if (h < 0) - return -1; /* can't fit in */ - - if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0) - return -1; - - D_forecv->c_slback->c_ye = ye; /* in case we modified it above */ - D_forecv->c_slorient = orient; /* in case it was UNKN */ - cv->c_slnext = D_forecv->c_slnext; - cv->c_slprev = D_forecv; - D_forecv->c_slnext = cv; - if (cv->c_slnext) - cv->c_slnext->c_slprev = cv; - cv->c_slorient = orient; - cv->c_slback = D_forecv->c_slback; - - cv->c_xs = xs; - cv->c_xe = xe; - cv->c_ys = ys; - cv->c_ye = ye; - cv->c_xoff = 0; - cv->c_yoff = 0; - cv->c_display = display; - cv->c_vplist = 0; - cv->c_captev.type = EV_TIMEOUT; - cv->c_captev.data = (char *)cv; - cv->c_captev.handler = cv_winid_fn; - - CanvasInitBlank(cv); - cv->c_lnext = 0; - - cv->c_next = 0; - - cv = cv->c_slback; - EqualizeCanvas(cv->c_slperp, 0); - ResizeCanvas(cv); - RecreateCanvasChain(); - RethinkDisplayViewports(); - ResizeLayersToCanvases(); - return 0; -} - -void -RemCanvas() -{ - int xs, xe, ys, ye; - struct canvas *cv; - - debug("RemCanvas\n"); - cv = D_forecv; - if (cv->c_slorient == SLICE_UNKN) - return; - while (cv->c_slprev) - cv = cv->c_slprev; - if (!cv->c_slnext) - return; - if (!cv->c_slnext->c_slnext && cv->c_slback->c_slback) - { - /* two canvases in slice, kill perp node */ - cv = D_forecv; - debug("deleting perp node\n"); - FreePerp(cv->c_slprev ? cv->c_slprev : cv->c_slnext); - FreePerp(cv->c_slback); - } - xs = cv->c_slback->c_xs; - xe = cv->c_slback->c_xe; - ys = cv->c_slback->c_ys; - ye = cv->c_slback->c_ye; - /* free canvas */ - cv = D_forecv; - D_forecv = cv->c_slprev; - if (!D_forecv) - D_forecv = cv->c_slnext; - FreeCanvas(cv); - - cv = D_forecv; - while (D_forecv->c_slperp) - D_forecv = D_forecv->c_slperp; - - /* if only one canvas left, set orient back to unknown */ - if (!cv->c_slnext && !cv->c_slprev && !cv->c_slback->c_slback && !cv->c_slperp) - { - cv->c_slorient = SLICE_UNKN; - if (!captionalways) - cv->c_slback->c_ye = ++ye; /* caption line no longer needed */ - } - cv = cv->c_slback; - EqualizeCanvas(cv->c_slperp, 0); - ResizeCanvas(cv); - - D_fore = Layer2Window(D_forecv->c_layer); - flayer = D_forecv->c_layer; - - RecreateCanvasChain(); - RethinkDisplayViewports(); - ResizeLayersToCanvases(); -} - -void -OneCanvas() -{ - struct canvas *cv = D_forecv, *ocv = 0; - - if (cv->c_slprev) - { - ocv = cv->c_slprev; - cv->c_slprev->c_slnext = cv->c_slnext; - } - if (cv->c_slnext) - { - ocv = cv->c_slnext; - cv->c_slnext->c_slprev = cv->c_slprev; - } - if (!ocv) - return; - if (cv->c_slback && cv->c_slback->c_slperp == cv) - cv->c_slback->c_slperp = ocv; - cv->c_slorient = SLICE_UNKN; - while (D_canvas.c_slperp) - FreeCanvas(D_canvas.c_slperp); - cv = D_forecv; - D_canvas.c_slperp = cv; - cv->c_slback = &D_canvas; - cv->c_slnext = 0; - cv->c_slprev = 0; - ASSERT(!cv->c_slperp); - if (!captionalways) - D_canvas.c_ye++; /* caption line no longer needed */ - ResizeCanvas(&D_canvas); - RecreateCanvasChain(); - RethinkDisplayViewports(); - ResizeLayersToCanvases(); -} - -int -RethinkDisplayViewports() -{ - struct canvas *cv; - struct viewport *vp, *vpn; - - /* free old viewports */ - for (cv = display->d_cvlist; cv; cv = cv->c_next) - { - for (vp = cv->c_vplist; vp; vp = vpn) - { - vp->v_canvas = 0; - vpn = vp->v_next; - bzero((char *)vp, sizeof(*vp)); - free(vp); - } - cv->c_vplist = 0; - } - display->d_vpxmin = -1; - display->d_vpxmax = -1; - - for (cv = display->d_cvlist; cv; cv = cv->c_next) - { - if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) - return -1; -#ifdef HOLE - vp->v_canvas = cv; - vp->v_xs = cv->c_xs; - vp->v_ys = (cv->c_ys + cv->c_ye) / 2; - vp->v_xe = cv->c_xe; - vp->v_ye = cv->c_ye; - vp->v_xoff = cv->c_xoff; - vp->v_yoff = cv->c_yoff; - vp->v_next = cv->c_vplist; - cv->c_vplist = vp; - - if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) - return -1; - vp->v_canvas = cv; - vp->v_xs = (cv->c_xs + cv->c_xe) / 2; - vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4; - vp->v_xe = cv->c_xe; - vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1; - vp->v_xoff = cv->c_xoff; - vp->v_yoff = cv->c_yoff; - vp->v_next = cv->c_vplist; - cv->c_vplist = vp; - - if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) - return -1; - vp->v_canvas = cv; - vp->v_xs = cv->c_xs; - vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4; - vp->v_xe = (3 * cv->c_xs + cv->c_xe) / 4 - 1; - vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1; - vp->v_xoff = cv->c_xoff; - vp->v_yoff = cv->c_yoff; - vp->v_next = cv->c_vplist; - cv->c_vplist = vp; - - if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) - return -1; - vp->v_canvas = cv; - vp->v_xs = cv->c_xs; - vp->v_ys = cv->c_ys; - vp->v_xe = cv->c_xe; - vp->v_ye = (3 * cv->c_ys + cv->c_ye) / 4 - 1; - vp->v_xoff = cv->c_xoff; - vp->v_yoff = cv->c_yoff; - vp->v_next = cv->c_vplist; - cv->c_vplist = vp; -#else - vp->v_canvas = cv; - vp->v_xs = cv->c_xs; - vp->v_ys = cv->c_ys; - vp->v_xe = cv->c_xe; - vp->v_ye = cv->c_ye; - vp->v_xoff = cv->c_xoff; - vp->v_yoff = cv->c_yoff; - vp->v_next = cv->c_vplist; - cv->c_vplist = vp; -#endif - - if (cv->c_xs < display->d_vpxmin || display->d_vpxmin == -1) - display->d_vpxmin = cv->c_xs; - if (cv->c_xe > display->d_vpxmax || display->d_vpxmax == -1) - display->d_vpxmax = cv->c_xe; - } - return 0; -} - -void -RethinkViewportOffsets(cv) -struct canvas *cv; -{ - struct viewport *vp; - - for (vp = cv->c_vplist; vp; vp = vp->v_next) - { - vp->v_xoff = cv->c_xoff; - vp->v_yoff = cv->c_yoff; - } -} - /* * if the adaptflag is on, we keep the size of this display, else * we may try to restore our old window sizes. @@ -1154,8 +435,8 @@ int adapt; ASSERT(display); ASSERT(D_tcinited); D_top = D_bot = -1; - AddCStr(D_TI); AddCStr(D_IS); + AddCStr(D_TI); /* Check for toggle */ if (D_IM && strcmp(D_IM, D_EI)) AddCStr(D_EI); @@ -1181,7 +462,7 @@ int adapt; ResizeDisplay(D_defwidth, D_defheight); ChangeScrollRegion(0, D_height - 1); D_x = D_y = 0; - Flush(); + Flush(3); ClearAll(); debug1("we %swant to adapt all our windows to the display\n", (adapt) ? "" : "don't "); @@ -1204,6 +485,8 @@ FinitTerm() KeypadMode(0); CursorkeysMode(0); CursorVisibility(0); + if (D_mousetrack) + D_mousetrack = 0; MouseMode(0); SetRendition(&mchar_null); SetFlow(FLOW_NOW); @@ -1222,7 +505,7 @@ FinitTerm() AddChar('\n'); AddCStr(D_TE); } - Flush(); + Flush(3); } @@ -1335,7 +618,15 @@ int c; AddCStr(D_CE0); goto addedutf8; } - AddUtf8(c); + if (c < 0x80) + { + if (D_xtable && D_xtable[(int)(unsigned char)D_rend.font] && D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c]) + AddStr(D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c]); + else + AddChar(c); + } + else + AddUtf8(c); goto addedutf8; } # endif @@ -1521,7 +812,13 @@ void MouseMode(mode) int mode; { - if (display && D_mouse != mode) + if (!display) + return; + + if (mode < D_mousetrack) + mode = D_mousetrack; + + if (D_mouse != mode) { char mousebuf[20]; if (!D_CXT) @@ -2660,7 +1957,7 @@ char *msg; return; /* XXX: better */ AddStr(msg); AddStr("\r\n"); - Flush(); + Flush(0); return; } if (!use_hardstatus || !D_HS) @@ -2677,19 +1974,11 @@ char *msg; if (strcmp(msg, D_status_lastmsg) == 0) { debug("same message - increase timeout"); - SetTimeout(&D_statusev, MsgWait); + if (!D_status_obufpos) + SetTimeout(&D_statusev, MsgWait); return; } - if (!D_status_bell) - { - struct timeval now; - int ti; - gettimeofday(&now, NULL); - ti = (now.tv_sec - D_status_time.tv_sec) * 1000 + (now.tv_usec - D_status_time.tv_usec) / 1000; - if (ti < MsgMinWait) - DisplaySleep1000(MsgMinWait - ti, 0); - } - RemoveStatus(); + RemoveStatusMinWait(); } for (s = t = msg; *s && t - msg < max; ++s) if (*s == BELL) @@ -2746,15 +2035,15 @@ char *msg; D_status = STATUS_ON_HS; ShowHStatus(msg); } - Flush(); - if (!display) - return; + + D_status_obufpos = D_obufp - D_obuf; + ASSERT(D_status_obufpos > 0); + if (D_status == STATUS_ON_WIN) { struct display *olddisplay = display; struct layer *oldflayer = flayer; - ASSERT(D_obuffree == D_obuflen); /* this is copied over from RemoveStatus() */ D_status = 0; GotoPos(0, STATLINE); @@ -2765,17 +2054,8 @@ char *msg; LaySetCursor(); display = olddisplay; flayer = oldflayer; - D_status_obuflen = D_obuflen; - D_status_obuffree = D_obuffree; - D_obuffree = D_obuflen = 0; D_status = STATUS_ON_WIN; } - gettimeofday(&D_status_time, NULL); - SetTimeout(&D_statusev, MsgWait); - evenq(&D_statusev); -#ifdef HAVE_BRAILLE - RefreshBraille(); /* let user see multiple Msg()s */ -#endif } void @@ -2798,6 +2078,7 @@ RemoveStatus() D_status_obuffree = -1; } D_status = 0; + D_status_obufpos = 0; D_status_bell = 0; evdeq(&D_statusev); olddisplay = display; @@ -2820,6 +2101,86 @@ RemoveStatus() flayer = oldflayer; } +/* Remove the status but make sure that it is seen for MsgMinWait ms */ +static void +RemoveStatusMinWait() +{ + /* XXX: should flush output first if D_status_obufpos is set */ + if (!D_status_bell && !D_status_obufpos) + { + struct timeval now; + int ti; + gettimeofday(&now, NULL); + ti = (now.tv_sec - D_status_time.tv_sec) * 1000 + (now.tv_usec - D_status_time.tv_usec) / 1000; + if (ti < MsgMinWait) + DisplaySleep1000(MsgMinWait - ti, 0); + } + RemoveStatus(); +} + +#ifdef UTF8 +static int +strlen_onscreen(unsigned char *c, unsigned char *end) +{ + int len = 0; + char *s = c; + while (*c && (!end || c < end)) + { + int v, dec = 0; + do + { + v = FromUtf8(*c++, &dec); + if (v == -2) + c--; + } + while (v < 0 && (!end || c < end)); + if (!utf8_iscomb(v)) + { + if (utf8_isdouble(v)) + len++; + len++; + } + } + + return len; +} + +static int +PrePutWinMsg(s, start, max) +char *s; +int start, max; +{ + /* Avoid double-encoding problem for a UTF-8 message on a UTF-8 locale. + Ideally, this would not be necessary. But fixing it the Right Way will + probably take way more time. So this will have to do for now. */ + if (D_encoding == UTF8) + { + int chars = strlen_onscreen(s + start, s + max); + D_encoding = 0; + PutWinMsg(s, start, max); + D_encoding = UTF8; + D_x -= (max - chars); /* Yak! But this is necessary to count for + the fact that not every byte represents a + character. */ + return start + chars; + } + else + { + PutWinMsg(s, start, max); + return max; + } +} +#else +static int +PrePutWinMsg(s, start, max) +char *s; +int start, max; +{ + PutWinMsg(s, start, max); + return max; +} +#endif + /* refresh the display's hstatus line */ void ShowHStatus(str) @@ -2864,7 +2225,7 @@ char *str; l = D_width; GotoPos(0, D_height - 1); SetRendition(captionalways || D_cvlist == 0 || D_cvlist->c_next ? &mchar_null: &mchar_so); - PutWinMsg(str, 0, l); + l = PrePutWinMsg(str, 0, l); if (!captionalways && D_cvlist && !D_cvlist->c_next) while (l++ < D_width) PUTCHARLP(' '); @@ -2966,26 +2327,7 @@ int y, from, to, isblank; return; /* can't refresh status */ } - /* The following check makes plenty of sense. Unfortunately, - vte-based terminals (notably gnome-terminal) experience a quirk - that causes the final line not to update properly when it falls outside - the scroll region; clearing the line with D_CE avoids the glitch, - so we'll disable this perfectly sensible shortcut until such a time - as widespread vte installations lack the glitch. - - See http://bugzilla.gnome.org/show_bug.cgi?id=542087 for current - status of the VTE bug report, and - https://savannah.gnu.org/bugs/index.php?23699 for the history from - the Savannah BTS. */ -#if 0 - if (y == D_height - 1 && D_has_hstatus == HSTATUS_LASTLINE) - { - RefreshHStatus(); - return; - } -#endif - - if (isblank == 0 && D_CE && to == D_width - 1 && from < to) + if (isblank == 0 && D_CE && to == D_width - 1 && from < to && D_status != STATUS_ON_HS) { GotoPos(from, y); if (D_UT || D_BE) @@ -2993,6 +2335,13 @@ int y, from, to, isblank; AddCStr(D_CE); isblank = 1; } + + if (y == D_height - 1 && D_has_hstatus == HSTATUS_LASTLINE) + { + RefreshHStatus(); + return; + } + while (from <= to) { lcv = 0; @@ -3011,7 +2360,7 @@ int y, from, to, isblank; SetRendition(&mchar_so); if (l > xx - cv->c_xs + 1) l = xx - cv->c_xs + 1; - PutWinMsg(buf, from - cv->c_xs, l); + l = PrePutWinMsg(buf, from - cv->c_xs, l); from = cv->c_xs + l; for (; from <= xx; from++) PUTCHARLP(' '); @@ -3181,8 +2530,8 @@ int from, to, y, bce; void DisplayLine(oml, ml, y, from, to) struct mline *oml, *ml; -int from, to, y;{ - +int from, to, y; +{ register int x; int last2flag = 0, delete_lp = 0; @@ -3503,12 +2852,19 @@ int newtop, newbot; } #ifdef RXVT_OSC +#define WT_FLAG "2" /* change to "0" to set both title and icon */ + void SetXtermOSC(i, s) int i; char *s; { - static char oscs[] = "1;\000\00020;\00039;\00049;\000"; + static char *oscs[][2] = { + { WT_FLAG ";", "screen" }, /* set window title */ + { "20;", "" }, /* background */ + { "39;", "black" }, /* default foreground (black?) */ + { "49;", "white" } /* default background (white?) */ + }; ASSERT(display); if (!D_CXT) @@ -3517,17 +2873,13 @@ char *s; s = ""; if (!D_xtermosc[i] && !*s) return; - if (i == 0 && !*s) - s = "screen"; /* always set icon name */ - if (i == 1 && !*s) - s = ""; /* no background */ - if (i == 2 && !*s) - s = "black"; /* black text */ - if (i == 3 && !*s) - s = "white"; /* on white background */ + if (i == 0 && !D_xtermosc[0]) + AddStr("\033[22;" WT_FLAG "t"); /* stack titles (xterm patch #251) */ + if (!*s) + s = oscs[i][1]; D_xtermosc[i] = 1; AddStr("\033]"); - AddStr(oscs + i * 4); + AddStr(oscs[i][0]); AddStr(s); AddChar(7); } @@ -3538,7 +2890,10 @@ ClearAllXtermOSC() int i; for (i = 3; i >= 0; i--) SetXtermOSC(i, 0); + if (D_xtermosc[0]) + AddStr("\033[23;" WT_FLAG "t"); /* unstack titles (xterm patch #251) */ } +#undef WT_FLAG #endif /* @@ -3588,9 +2943,11 @@ int n; } void -Flush() +Flush(progress) +int progress; { register int l; + int wr; register char *p; ASSERT(display); @@ -3606,29 +2963,57 @@ Flush() return; } p = D_obuf; - if (fcntl(D_userfd, F_SETFL, 0)) - debug1("Warning: BLOCK fcntl failed: %d\n", errno); + if (!progress) + { + if (fcntl(D_userfd, F_SETFL, 0)) + debug1("Warning: BLOCK fcntl failed: %d\n", errno); + } while (l) { - register int wr; + if (progress) + { + fd_set w; + FD_ZERO(&w); + FD_SET(D_userfd, &w); + struct timeval t; + t.tv_sec = progress; + t.tv_usec = 0; + wr = select(FD_SETSIZE, (fd_set *)0, &w, (fd_set *)0, &t); + if (wr == -1) + { + if (errno == EINTR) + continue; + debug1("Warning: select failed: %d\n", errno); + break; + } + if (wr == 0) + { + /* no progress after 3 seconds. sorry. */ + debug1("Warning: no progress after %d seconds\n", progress); + break; + } + } wr = write(D_userfd, p, l); - if (wr <= 0) + if (wr <= 0) { - if (errno == EINTR) + if (errno == EINTR) continue; debug1("Writing to display: %d\n", errno); - wr = l; + break; } - if (!display) - return; D_obuffree += wr; p += wr; l -= wr; } + if (l) + debug1("Warning: Flush could not write %d bytes\n", l); D_obuffree += l; D_obufp = D_obuf; - if (fcntl(D_userfd, F_SETFL, FNBLOCK)) - debug1("Warning: NBLOCK fcntl failed: %d\n", errno); + if (!progress) + { + if (fcntl(D_userfd, F_SETFL, FNBLOCK)) + debug1("Warning: NBLOCK fcntl failed: %d\n", errno); + } if (D_blocked == 1) D_blocked = 0; D_blocked_fuzz = 0; @@ -3666,16 +3051,7 @@ Resize_obuf() if (D_status_obuffree >= 0) { ASSERT(D_obuffree == -1); - if (!D_status_bell) - { - struct timeval now; - int ti; - gettimeofday(&now, NULL); - ti = (now.tv_sec - D_status_time.tv_sec) * 1000 + (now.tv_usec - D_status_time.tv_usec) / 1000; - if (ti < MsgMinWait) - DisplaySleep1000(MsgMinWait - ti, 0); - } - RemoveStatus(); + RemoveStatusMinWait(); if (--D_obuffree > 0) /* redo AddChar decrement */ return; } @@ -3757,8 +3133,8 @@ NukePending() D_obufp = D_obuf; D_obuffree += len; D_top = D_bot = -1; - AddCStr(D_TI); AddCStr(D_IS); + AddCStr(D_TI); /* Turn off all attributes. (Tim MacKenzie) */ if (D_ME) AddCStr(D_ME); @@ -3843,6 +3219,8 @@ char *data; len = D_obufp - D_obuf; if (len < size) size = len; + if (D_status_obufpos && size > D_status_obufpos) + size = D_status_obufpos; ASSERT(len >= 0); size = write(D_userfd, D_obuf, size); if (size >= 0) @@ -3855,6 +3233,30 @@ char *data; } D_obufp -= size; D_obuffree += size; + if (D_status_obufpos) + { + D_status_obufpos -= size; + if (!D_status_obufpos) + { + debug("finished writing the status message\n"); + /* we're finished displaying the message! */ + if (D_status == STATUS_ON_WIN) + { + /* setup continue trigger */ + D_status_obuflen = D_obuflen; + D_status_obuffree = D_obuffree; + /* setting obbuffree to 0 will make AddChar call + * ResizeObuf */ + D_obuffree = D_obuflen = 0; + } + gettimeofday(&D_status_time, NULL); + SetTimeout(&D_statusev, MsgWait); + evenq(&D_statusev); +#ifdef HAVE_BRAILLE + RefreshBraille(); /* let user see multiple Msg()s */ +#endif + } + } if (D_blocked_fuzz) { D_blocked_fuzz -= size; @@ -3882,7 +3284,7 @@ char *data; Activate(D_fore ? D_fore->w_norefresh : 0); D_blocked_fuzz = D_obufp - D_obuf; } - } + } else { #ifdef linux @@ -4016,15 +3418,29 @@ char *data; y = bp[4] - 33; if (x >= D_forecv->c_xs && x <= D_forecv->c_xe && y >= D_forecv->c_ys && y <= D_forecv->c_ye) { - x -= D_forecv->c_xoff; - y -= D_forecv->c_yoff; - if (x >= 0 && x < D_forecv->c_layer->l_width && y >= 0 && y < D_forecv->c_layer->l_height) + if ((D_fore && D_fore->w_mouse) || (D_mousetrack && D_forecv->c_layer->l_mode == 1)) + { + /* Send clicks only if the window is expecting clicks */ + x -= D_forecv->c_xoff; + y -= D_forecv->c_yoff; + if (x >= 0 && x < D_forecv->c_layer->l_width && y >= 0 && y < D_forecv->c_layer->l_height) + { + bp[3] = x + 33; + bp[4] = y + 33; + i -= 4; + bp += 4; + continue; + } + } + } + else if (D_mousetrack && bp[2] == '#') + { + /* 'focus' to the clicked region, only on mouse up */ + struct canvas *cv = FindCanvas(x, y); + if (cv) { - bp[3] = x + 33; - bp[4] = y + 33; - i -= 4; - bp += 4; - continue; + SetForeCanvas(display, cv); + /* XXX: Do we want to reset the input buffer? */ } } if (bp[0] == '[') @@ -4121,29 +3537,6 @@ char *data; } } -static void -cv_winid_fn(ev, data) -struct event *ev; -char *data; -{ - int ox, oy; - struct canvas *cv = (struct canvas *)data; - - display = cv->c_display; - if (D_status == STATUS_ON_WIN) - { - SetTimeout(ev, 1); - evenq(ev); - return; - } - ox = D_x; - oy = D_y; - if (cv->c_ye + 1 < D_height) - RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); - if (ox != -1 && oy != -1) - GotoPos(ox, oy); -} - #ifdef MAPKEYS static void disp_map_fn(ev, data) @@ -4367,7 +3760,7 @@ char **cmdv; #endif display = 0; execvpe(*cmdv, cmdv, NewEnv + 3); - Panic(errno, *cmdv); + Panic(errno, "%s", *cmdv); default: break; } @@ -4377,338 +3770,6 @@ char **cmdv; ClearAll(); } -#endif - -struct layout *layouts; -struct layout *laytab[MAXLAY]; -struct layout *layout_last, layout_last_marker; -struct layout *layout_attach = &layout_last_marker; - -void -FreeLayoutCv(cv) -struct canvas *cv; -{ - struct canvas *cnext, *c = cv; - for (; cv; cv = cnext) - { - if (cv->c_slperp) - { - FreeLayoutCv(cv->c_slperp); - free(cv->c_slperp); - cv->c_slperp = 0; - } - cnext = cv->c_slnext; - cv->c_slnext = 0; - if (cv != c) - free(cv); - } -} - -static void -DupLayoutCv(cvf, cvt, save) -struct canvas *cvf, *cvt; -int save; -{ - while(cvf) - { - cvt->c_slorient = cvf->c_slorient; - cvt->c_slweight = cvf->c_slweight; - if (cvf == D_forecv) - D_forecv = cvt; - if (!save) - { - cvt->c_display = display; - if (!cvf->c_slperp) - { - cvt->c_captev.type = EV_TIMEOUT; - cvt->c_captev.data = (char *)cvt; - cvt->c_captev.handler = cv_winid_fn; - cvt->c_blank.l_cvlist = 0; - cvt->c_blank.l_layfn = &BlankLf; - cvt->c_blank.l_bottom = &cvt->c_blank; - } - cvt->c_layer = cvf->c_layer; - } - else - { - struct win *p = cvf->c_layer ? Layer2Window(cvf->c_layer) : 0; - cvt->c_layer = p ? &p->w_layer : 0; - } - if (cvf->c_slperp) - { - cvt->c_slperp = (struct canvas *)calloc(1, sizeof(struct canvas)); - cvt->c_slperp->c_slback = cvt; - CanvasInitBlank(cvt->c_slperp); - DupLayoutCv(cvf->c_slperp, cvt->c_slperp, save); - } - if (cvf->c_slnext) - { - cvt->c_slnext = (struct canvas *)calloc(1, sizeof(struct canvas)); - cvt->c_slnext->c_slprev = cvt; - cvt->c_slnext->c_slback = cvt->c_slback; - CanvasInitBlank(cvt->c_slnext); - } - cvf = cvf->c_slnext; - cvt = cvt->c_slnext; - } -} - -void -PutWindowCv(cv) -struct canvas *cv; -{ - struct win *p; - for (; cv; cv = cv->c_slnext) - { - if (cv->c_slperp) - { - PutWindowCv(cv->c_slperp); - continue; - } - p = cv->c_layer ? (struct win *)cv->c_layer->l_data : 0; - cv->c_layer = 0; - SetCanvasWindow(cv, p); - } -} - -struct layout * -CreateLayout(title, startat) -char *title; -int startat; -{ - struct layout *lay; - int i; - - if (startat >= MAXLAY || startat < 0) - startat = 0; - for (i = startat; ;) - { - if (!laytab[i]) - break; - if (++i == MAXLAY) - i = 0; - if (i == startat) - { - Msg(0, "No more layouts\n"); - return 0; - } - } - lay = (struct layout *)calloc(1, sizeof(*lay)); - lay->lay_title = SaveStr(title); - lay->lay_autosave = 1; - lay->lay_number = i; - laytab[i] = lay; - lay->lay_next = layouts; - layouts = lay; - return lay; -} - -void -SaveLayout(name, cv) -char *name; -struct canvas *cv; -{ - struct layout *lay; - struct canvas *fcv; - for (lay = layouts; lay; lay = lay->lay_next) - if (!strcmp(lay->lay_title, name)) - break; - if (lay) - FreeLayoutCv(&lay->lay_canvas); - else - lay = CreateLayout(name, 0); - if (!lay) - return; - fcv = D_forecv; - DupLayoutCv(cv, &lay->lay_canvas, 1); - lay->lay_forecv = D_forecv; - D_forecv = fcv; - D_layout = lay; -} - -void -AutosaveLayout(lay) -struct layout *lay; -{ - struct canvas *fcv; - if (!lay || !lay->lay_autosave) - return; - FreeLayoutCv(&lay->lay_canvas); - fcv = D_forecv; - DupLayoutCv(&D_canvas, &lay->lay_canvas, 1); - lay->lay_forecv = D_forecv; - D_forecv = fcv; -} - -struct layout * -FindLayout(name) -char *name; -{ - struct layout *lay; - char *s; - int i; - for (i = 0, s = name; *s >= '0' && *s <= '9'; s++) - i = i * 10 + (*s - '0'); - if (!*s && s != name && i >= 0 && i < MAXLAY) - return laytab[i]; - for (lay = layouts; lay; lay = lay->lay_next) - if (!strcmp(lay->lay_title, name)) - break; - return lay; -} - -void -LoadLayout(lay, cv) -struct layout *lay; -struct canvas *cv; -{ - AutosaveLayout(D_layout); - if (!lay) - { - while (D_canvas.c_slperp) - FreeCanvas(D_canvas.c_slperp); - MakeDefaultCanvas(); - SetCanvasWindow(D_forecv, 0); - D_layout = 0; - return; - } - while (D_canvas.c_slperp) - FreeCanvas(D_canvas.c_slperp); - D_cvlist = 0; - D_forecv = lay->lay_forecv; - DupLayoutCv(&lay->lay_canvas, &D_canvas, 0); - D_canvas.c_ye = D_height - 1 - ((D_canvas.c_slperp && D_canvas.c_slperp->c_slnext) || captionalways) - (D_has_hstatus == HSTATUS_LASTLINE); - ResizeCanvas(&D_canvas); - RecreateCanvasChain(); - RethinkDisplayViewports(); - PutWindowCv(&D_canvas); - ResizeLayersToCanvases(); - D_layout = lay; -} - -void -NewLayout(title, startat) -char *title; -int startat; -{ - struct layout *lay; - struct canvas *fcv; - - lay = CreateLayout(title, startat); - if (!lay) - return; - LoadLayout(0, &D_canvas); - fcv = D_forecv; - DupLayoutCv(&D_canvas, &lay->lay_canvas, 1); - lay->lay_forecv = D_forecv; - D_forecv = fcv; - D_layout = lay; - lay->lay_autosave = 1; -} - -static char * -AddLayoutsInfo(buf, len, where) -char *buf; -int len; -int where; -{ - char *s, *ss, *t; - struct layout *p, **pp; - int l; - - s = ss = buf; - for (pp = laytab; pp < laytab + MAXLAY; pp++) - { - if (pp - laytab == where && ss == buf) - ss = s; - if ((p = *pp) == 0) - continue; - t = p->lay_title; - l = strlen(t); - if (l > 20) - l = 20; - if (s - buf + l > len - 24) - break; - if (s > buf) - { - *s++ = ' '; - *s++ = ' '; - } - sprintf(s, "%d", p->lay_number); - if (p->lay_number == where) - ss = s; - s += strlen(s); - if (display && p == D_layout) - *s++ = '*'; - *s++ = ' '; - strncpy(s, t, l); - s += l; - } - *s = 0; - return ss; -} - -void -ShowLayouts(where) -int where; -{ - char buf[1024]; - char *s, *ss; +#endif /* BLANKER_PRG */ - if (!display) - return; - if (!layouts) - { - Msg(0, "No layouts defined\n"); - return; - } - if (where == -1 && D_layout) - where = D_layout->lay_number; - ss = AddLayoutsInfo(buf, sizeof(buf), where); - s = buf + strlen(buf); - if (ss - buf > D_width / 2) - { - ss -= D_width / 2; - if (s - ss < D_width) - { - ss = s - D_width; - if (ss < buf) - ss = buf; - } - } - else - ss = buf; - Msg(0, "%s", ss); -} - -void -RemoveLayout(lay) -struct layout *lay; -{ - struct layout **layp = &layouts; - - for (; *layp; layp = &(*layp)->lay_next) - { - if (*layp == lay) - { - *layp = lay->lay_next; - break; - } - } - laytab[lay->lay_number] = (struct layout *)0; - - if (display && D_layout == lay) - D_layout = (struct layout *)0; - - FreeLayoutCv(&lay->lay_canvas); - - if (lay->lay_title) - free(lay->lay_title); - free(lay); - - if (layouts) - LoadLayout((display && D_layout) ? D_layout : *layp ? *layp : layouts, - display ? &D_canvas : (struct canvas *)0); - Activate(0); -} |