[BACK]Return to status.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Diff for /src/usr.bin/tmux/status.c between version 1.47 and 1.48

version 1.47, 2009/11/19 16:22:10 version 1.48, 2009/11/19 19:47:28
Line 29 
Line 29 
   
 #include "tmux.h"  #include "tmux.h"
   
   char   *status_redraw_get_left(
               struct client *, time_t, int, struct grid_cell *, size_t *);
   char   *status_redraw_get_right(
               struct client *, time_t, int, struct grid_cell *, size_t *);
 char   *status_job(struct client *, char **);  char   *status_job(struct client *, char **);
 void    status_job_callback(struct job *);  void    status_job_callback(struct job *);
 size_t  status_width(struct client *, struct winlink *, time_t);  size_t  status_width(struct client *, struct winlink *, time_t);
Line 41 
Line 45 
 void    status_prompt_add_history(struct client *);  void    status_prompt_add_history(struct client *);
 char   *status_prompt_complete(const char *);  char   *status_prompt_complete(const char *);
   
   /* Retrieve options for left string. */
   char *
   status_redraw_get_left(struct client *c,
       time_t t, int utf8flag, struct grid_cell *gc, size_t *size)
   {
           struct session  *s = c->session;
           char            *left;
           u_char           fg, bg, attr;
           size_t           leftlen;
   
           fg = options_get_number(&s->options, "status-left-fg");
           if (fg != 8)
                   colour_set_fg(gc, fg);
           bg = options_get_number(&s->options, "status-left-bg");
           if (bg != 8)
                   colour_set_bg(gc, bg);
           attr = options_get_number(&s->options, "status-left-attr");
           if (attr != 0)
                   gc->attr = attr;
   
           left = status_replace(
               c, NULL, options_get_string(&s->options, "status-left"), t, 1);
   
           *size = options_get_number(&s->options, "status-left-length");
           leftlen = screen_write_cstrlen(utf8flag, "%s", left);
           if (leftlen < *size)
                   *size = leftlen;
           return (left);
   }
   
   /* Retrieve options for right string. */
   char *
   status_redraw_get_right(struct client *c,
       time_t t, int utf8flag, struct grid_cell *gc, size_t *size)
   {
           struct session  *s = c->session;
           char            *right;
           u_char           fg, bg, attr;
           size_t           rightlen;
   
           fg = options_get_number(&s->options, "status-right-fg");
           if (fg != 8)
                   colour_set_fg(gc, fg);
           bg = options_get_number(&s->options, "status-right-bg");
           if (bg != 8)
                   colour_set_bg(gc, bg);
           attr = options_get_number(&s->options, "status-right-attr");
           if (attr != 0)
                   gc->attr = attr;
   
           right = status_replace(
               c, NULL, options_get_string(&s->options, "status-right"), t, 1);
   
           *size = options_get_number(&s->options, "status-right-length");
           rightlen = screen_write_cstrlen(utf8flag, "%s", right);
           if (rightlen < *size)
                   *size = rightlen;
           return (right);
   }
   
 /* Draw status for client on the last lines of given context. */  /* Draw status for client on the last lines of given context. */
 int  int
 status_redraw(struct client *c)  status_redraw(struct client *c)
 {  {
         struct screen_write_ctx         ctx;          struct screen_write_ctx ctx;
         struct session                 *s = c->session;          struct session         *s = c->session;
         struct winlink                 *wl;          struct winlink         *wl;
         struct screen                   old_status;          struct screen           old_status, window_list;
         char                           *left, *right, *text, *ptr;          struct grid_cell        stdgc, lgc, rgc, gc;
         size_t                          llen, llen2, rlen, rlen2, offset;          time_t                  t;
         size_t                          ox, xx, yy, size, start, width;          char                   *left, *right;
         struct grid_cell                stdgc, sl_stdgc, sr_stdgc, gc;          u_int                   offset, needed;
         int                             larrow, rarrow, utf8flag;          u_int                   wlstart, wlwidth, wlavailable, wloffset, wlsize;
         int                             sl_fg, sl_bg, sr_fg, sr_bg;          size_t                  llen, rlen;
         int                             sl_attr, sr_attr;          int                     larrow, rarrow, utf8flag;
   
         left = right = NULL;  
   
         /* No status line?*/          /* No status line?*/
         if (c->tty.sy == 0 || !options_get_number(&s->options, "status"))          if (c->tty.sy == 0 || !options_get_number(&s->options, "status"))
                 return (1);                  return (1);
           left = right = NULL;
         larrow = rarrow = 0;          larrow = rarrow = 0;
   
         /* Create the target screen. */          /* Update status timer. */
         memcpy(&old_status, &c->status, sizeof old_status);  
         screen_init(&c->status, c->tty.sx, 1, 0);  
   
         if (gettimeofday(&c->status_timer, NULL) != 0)          if (gettimeofday(&c->status_timer, NULL) != 0)
                 fatal("gettimeofday failed");                  fatal("gettimeofday failed");
           t = c->status_timer.tv_sec;
   
           /* Set up default colour. */
         memcpy(&stdgc, &grid_default_cell, sizeof gc);          memcpy(&stdgc, &grid_default_cell, sizeof gc);
         colour_set_fg(&stdgc, options_get_number(&s->options, "status-fg"));          colour_set_fg(&stdgc, options_get_number(&s->options, "status-fg"));
         colour_set_bg(&stdgc, options_get_number(&s->options, "status-bg"));          colour_set_bg(&stdgc, options_get_number(&s->options, "status-bg"));
         stdgc.attr |= options_get_number(&s->options, "status-attr");          stdgc.attr |= options_get_number(&s->options, "status-attr");
   
         /*          /* Create the target screen. */
          * Set the status-left and status-right parts to the default status          memcpy(&old_status, &c->status, sizeof old_status);
          * line options and only change them where they differ from the          screen_init(&c->status, c->tty.sx, 1, 0);
          * defaults.          screen_write_start(&ctx, NULL, &c->status);
          */          for (offset = 0; offset < c->tty.sx; offset++)
         memcpy(&sl_stdgc, &stdgc, sizeof sl_stdgc);                  screen_write_putc(&ctx, &stdgc, ' ');
         memcpy(&sr_stdgc, &stdgc, sizeof sr_stdgc);          screen_write_stop(&ctx);
         sl_fg = options_get_number(&s->options, "status-left-fg");  
         if (sl_fg != 8)  
                 colour_set_fg(&sl_stdgc, sl_fg);  
         sl_bg = options_get_number(&s->options, "status-left-bg");  
         if (sl_bg != 8)  
                 colour_set_bg(&sl_stdgc, sl_bg);  
         sl_attr = options_get_number(&s->options, "status-left-attr");  
         if (sl_attr != 0)  
                 sl_stdgc.attr = sl_attr;  
         sr_fg = options_get_number(&s->options, "status-right-fg");  
         if (sr_fg != 8)  
                 colour_set_fg(&sr_stdgc, sr_fg);  
         sr_bg = options_get_number(&s->options, "status-right-bg");  
         if (sr_bg != 8)  
                 colour_set_bg(&sr_stdgc, sr_bg);  
         sr_attr = options_get_number(&s->options, "status-right-attr");  
         if (sr_attr != 0)  
                 sr_stdgc.attr = sr_attr;  
   
         yy = c->tty.sy - 1;          /* If the height is one line, blank status line. */
         if (yy == 0)          if (c->tty.sy <= 1)
                 goto blank;                  goto out;
   
         /* Caring about UTF-8 in status line? */          /* Get UTF-8 flag. */
         utf8flag = options_get_number(&s->options, "status-utf8");          utf8flag = options_get_number(&s->options, "status-utf8");
   
         /* Work out the left and right strings. */          /* Work out left and right strings. */
         left = status_replace(c, NULL, options_get_string(          memcpy(&lgc, &stdgc, sizeof lgc);
             &s->options, "status-left"), c->status_timer.tv_sec, 1);          left = status_redraw_get_left(c, t, utf8flag, &lgc, &llen);
         llen = options_get_number(&s->options, "status-left-length");          memcpy(&rgc, &stdgc, sizeof rgc);
         llen2 = screen_write_cstrlen(utf8flag, "%s", left);          right = status_redraw_get_right(c, t, utf8flag, &rgc, &rlen);
         if (llen2 < llen)  
                 llen = llen2;  
   
         right = status_replace(c, NULL, options_get_string(  
             &s->options, "status-right"), c->status_timer.tv_sec, 1);  
         rlen = options_get_number(&s->options, "status-right-length");  
         rlen2 = screen_write_cstrlen(utf8flag, "%s", right);  
         if (rlen2 < rlen)  
                 rlen = rlen2;  
   
         /*          /*
          * Figure out how much space we have for the window list. If there isn't           * Figure out how much space we have for the window list. If there
          * enough space, just wimp out.           * isn't enough space, just show a blank status line.
          */           */
         xx = 0;          needed = 0;
         if (llen != 0)          if (llen != 0)
                 xx += llen + 1;                  needed += llen + 1;
         if (rlen != 0)          if (rlen != 0)
                 xx += rlen + 1;                  needed += rlen + 1;
         if (c->tty.sx == 0 || c->tty.sx <= xx)          if (c->tty.sx == 0 || c->tty.sx <= needed)
                 goto blank;                  goto out;
         xx = c->tty.sx - xx;          wlavailable = c->tty.sx - needed;
   
         /*          /* Calculate the total size needed for the window list. */
          * Right. We have xx characters to fill. Find out how much is to go in          wlstart = wloffset = wlwidth = 0;
          * them and the offset of the current window (it must be on screen).  
          */  
         width = offset = 0;  
         RB_FOREACH(wl, winlinks, &s->windows) {          RB_FOREACH(wl, winlinks, &s->windows) {
                 size = status_width(c, wl, c->status_timer.tv_sec) + 1;                  if (wl->status_text != NULL)
                           xfree(wl->status_text);
                   memcpy(&wl->status_cell, &stdgc, sizeof wl->status_cell);
                   wl->status_text = status_print(c, wl, t, &wl->status_cell);
                   wl->status_width =
                       screen_write_cstrlen(utf8flag, "%s", wl->status_text);
   
                 if (wl == s->curw)                  if (wl == s->curw)
                         offset = width;                          wloffset = wlwidth;
                 width += size;                  wlwidth += wl->status_width + 1;
         }          }
         start = 0;  
   
         /* If there is enough space for the total width, all is gravy. */          /* Create a new screen for the window list. */
         if (width <= xx)          screen_init(&window_list, wlwidth, 1, 0);
   
           /* And draw the window list into it. */
           screen_write_start(&ctx, NULL, &window_list);
           RB_FOREACH(wl, winlinks, &s->windows) {
                   screen_write_cnputs(&ctx,
                       -1, &wl->status_cell, utf8flag, "%s", wl->status_text);
                   screen_write_putc(&ctx, &stdgc, ' ');
           }
           screen_write_stop(&ctx);
   
           /* If there is enough space for the total width, skip to draw now. */
           if (wlwidth <= wlavailable)
                 goto draw;                  goto draw;
   
         /* Find size of current window text. */          /* Find size of current window text. */
         size = status_width(c, s->curw, c->status_timer.tv_sec);          wlsize = s->curw->status_width;
   
         /*          /*
          * If the offset is already on screen, we're good to draw from the           * If the current window is already on screen, good to draw from the
          * start and just leave off the end.           * start and just leave off the end.
          */           */
         if (offset + size < xx) {          if (wloffset + wlsize < wlavailable) {
                 if (xx > 0) {                  if (wlavailable > 0) {
                         rarrow = 1;                          rarrow = 1;
                         xx--;                          wlavailable--;
                 }                  }
                   wlwidth = wlavailable;
                 width = xx;  
                 goto draw;  
         }  
   
         /*  
          * Work out how many characters we need to omit from the start. There  
          * are xx characters to fill, and offset + size must be the last. So,  
          * the start character is offset + size - xx.  
          */  
         if (xx > 0) {  
                 larrow = 1;  
                 xx--;  
         }  
   
         start = offset + size - xx;  
         if (xx > 0 && width > start + xx + 1) { /* + 1, eh? */  
                 rarrow = 1;  
                 start++;  
                 xx--;  
         }  
         width = xx;  
   
 draw:  
         /* Bail here if anything is too small too. XXX. */  
         if (width == 0 || xx == 0)  
                 goto blank;  
   
         /* Begin drawing and move to the starting position. */  
         screen_write_start(&ctx, NULL, &c->status);  
         if (llen != 0) {  
                 screen_write_cursormove(&ctx, 0, yy);  
                 screen_write_cnputs(&ctx, llen, &sl_stdgc, utf8flag, "%s", left);  
                 screen_write_putc(&ctx, &stdgc, ' ');  
                 if (larrow)  
                         screen_write_putc(&ctx, &stdgc, ' ');  
         } else {          } else {
                 if (larrow)                  /*
                         screen_write_cursormove(&ctx, 1, yy);                   * Work out how many characters we need to omit from the
                 else                   * start. There are wlavailable characters to fill, and
                         screen_write_cursormove(&ctx, 0, yy);                   * wloffset + wlsize must be the last. So, the start character
                    * is wloffset + wlsize - wlavailable.
                    */
                   if (wlavailable > 0) {
                           larrow = 1;
                           wlavailable--;
                   }
   
                   wlstart = wloffset + wlsize - wlavailable;
                   if (wlavailable > 0 && wlwidth > wlstart + wlavailable + 1) {
                           rarrow = 1;
                           wlstart++;
                           wlavailable--;
                   }
                   wlwidth = wlavailable;
         }          }
   
         ox = 0;          /* Bail if anything is now too small too. */
         if (width < xx) {          if (wlwidth == 0 || wlavailable == 0) {
                 switch (options_get_number(&s->options, "status-justify")) {                  screen_free(&window_list);
                 case 1: /* centered */                  goto out;
                         ox = 1 + (xx - width) / 2;  
                         break;  
                 case 2: /* right */  
                         ox = 1 + (xx - width);  
                         break;  
                 }  
                 xx -= ox;  
                 while (ox-- > 0)  
                         screen_write_putc(&ctx, &stdgc, ' ');  
         }          }
   
         /* Draw each character in succession. */          /*
            * Now the start position is known, work out the state of the left and
            * right arrows.
            */
         offset = 0;          offset = 0;
         RB_FOREACH(wl, winlinks, &s->windows) {          RB_FOREACH(wl, winlinks, &s->windows) {
                 memcpy(&gc, &stdgc, sizeof gc);                  if (larrow == 1 && offset < wlstart) {
                 text = status_print(c, wl, c->status_timer.tv_sec, &gc);  
   
                 if (larrow == 1 && offset < start) {  
                         if (session_alert_has(s, wl, WINDOW_ACTIVITY))                          if (session_alert_has(s, wl, WINDOW_ACTIVITY))
                                 larrow = -1;                                  larrow = -1;
                         else if (session_alert_has(s, wl, WINDOW_BELL))                          else if (session_alert_has(s, wl, WINDOW_BELL))
Line 238 
Line 258 
                                 larrow = -1;                                  larrow = -1;
                 }                  }
   
                 ptr = text;                  offset += wl->status_width;
                 for (; offset < start; offset++)  
                         ptr++;  /* XXX should skip UTF-8 characters */  
                 if (offset < start + width) {  
                         screen_write_cnputs(&ctx,  
                             start + width - offset, &gc, utf8flag, "%s", text);  
                         offset += screen_write_cstrlen(utf8flag, "%s", text);  
                 }  
   
                 if (rarrow == 1 && offset > start + width) {                  if (rarrow == 1 && offset > wlstart + wlwidth) {
                         if (session_alert_has(s, wl, WINDOW_ACTIVITY))                          if (session_alert_has(s, wl, WINDOW_ACTIVITY))
                                 rarrow = -1;                                  rarrow = -1;
                         else if (session_alert_has(s, wl, WINDOW_BELL))                          else if (session_alert_has(s, wl, WINDOW_BELL))
Line 255 
Line 268 
                         else if (session_alert_has(s, wl, WINDOW_CONTENT))                          else if (session_alert_has(s, wl, WINDOW_CONTENT))
                                 rarrow = -1;                                  rarrow = -1;
                 }                  }
   
                 if (offset < start + width) {  
                         if (offset >= start) {  
                                 screen_write_putc(&ctx, &stdgc, ' ');  
                         }  
                         offset++;  
                 }  
   
                 xfree(text);  
         }          }
   
         /* Fill the remaining space if any. */  draw:
         while (offset++ < xx)          /* Begin drawing. */
                 screen_write_putc(&ctx, &stdgc, ' ');          screen_write_start(&ctx, NULL, &c->status);
   
         /* Draw the last item. */          /* Draw the left string and arrow. */
         if (rlen != 0) {          screen_write_cursormove(&ctx, 0, 0);
                 screen_write_cursormove(&ctx, c->tty.sx - rlen - 1, yy);          if (llen != 0) {
                   screen_write_cnputs(&ctx, llen, &lgc, utf8flag, "%s", left);
                 screen_write_putc(&ctx, &stdgc, ' ');                  screen_write_putc(&ctx, &stdgc, ' ');
                 screen_write_cnputs(&ctx, rlen, &sr_stdgc, utf8flag, "%s", right);  
         }          }
   
         /* Draw the arrows. */  
         if (larrow != 0) {          if (larrow != 0) {
                 memcpy(&gc, &stdgc, sizeof gc);                  memcpy(&gc, &stdgc, sizeof gc);
                 if (larrow == -1)                  if (larrow == -1)
                         gc.attr ^= GRID_ATTR_REVERSE;                          gc.attr ^= GRID_ATTR_REVERSE;
                 if (llen != 0)  
                         screen_write_cursormove(&ctx, llen + 1, yy);  
                 else  
                         screen_write_cursormove(&ctx, 0, yy);  
                 screen_write_putc(&ctx, &gc, '<');                  screen_write_putc(&ctx, &gc, '<');
         }          }
   
           /* Draw the right string and arrow. */
         if (rarrow != 0) {          if (rarrow != 0) {
                   screen_write_cursormove(&ctx, c->tty.sx - rlen - 2, 0);
                 memcpy(&gc, &stdgc, sizeof gc);                  memcpy(&gc, &stdgc, sizeof gc);
                 if (rarrow == -1)                  if (rarrow == -1)
                         gc.attr ^= GRID_ATTR_REVERSE;                          gc.attr ^= GRID_ATTR_REVERSE;
                 if (rlen != 0)  
                         screen_write_cursormove(&ctx, c->tty.sx - rlen - 2, yy);  
                 else  
                         screen_write_cursormove(&ctx, c->tty.sx - 1, yy);  
                 screen_write_putc(&ctx, &gc, '>');                  screen_write_putc(&ctx, &gc, '>');
           } else
                   screen_write_cursormove(&ctx, c->tty.sx - rlen - 1, 0);
           if (rlen != 0) {
                   screen_write_putc(&ctx, &stdgc, ' ');
                   screen_write_cnputs(&ctx, rlen, &rgc, utf8flag, "%s", right);
         }          }
   
         goto out;          /* Figure out the offset for the window list. */
           wloffset = 1;
           if (wlwidth < wlavailable) {
                   switch (options_get_number(&s->options, "status-justify")) {
                   case 1: /* centered */
                           wloffset = 1 + (wlavailable - wlwidth) / 2;
                           break;
                   case 2: /* right */
                           wloffset = 1 + (wlavailable - wlwidth);
                           break;
                   }
           }
           wloffset += llen;
           if (larrow != 0)
                   wloffset++;
   
 blank:          /* Copy the window list. */
         /* Just draw the whole line as blank. */          screen_write_cursormove(&ctx, wloffset, 0);
         screen_write_start(&ctx, NULL, &c->status);          screen_write_copy(&ctx, &window_list, wlstart, 0, wlwidth, 1);
         screen_write_cursormove(&ctx, 0, yy);          screen_free(&window_list);
         for (offset = 0; offset < c->tty.sx; offset++)  
                 screen_write_putc(&ctx, &stdgc, ' ');  
   
 out:  
         screen_write_stop(&ctx);          screen_write_stop(&ctx);
   
   out:
         if (left != NULL)          if (left != NULL)
                 xfree(left);                  xfree(left);
         if (right != NULL)          if (right != NULL)

Legend:
Removed from v.1.47  
changed lines
  Added in v.1.48