diff src/redisplay.c @ 265:8efd647ea9ca r20-5b31

Import from CVS: tag r20-5b31
author cvs
date Mon, 13 Aug 2007 10:25:37 +0200
parents 11cf20601dec
children 966663fcf606
line wrap: on
line diff
--- a/src/redisplay.c	Mon Aug 13 10:24:47 2007 +0200
+++ b/src/redisplay.c	Mon Aug 13 10:25:37 2007 +0200
@@ -247,6 +247,7 @@
 static void generate_modeline (struct window *w, struct display_line *dl,
 			       int type);
 static int ensure_modeline_generated (struct window *w, int type);
+#ifdef MODELINE_IS_SCROLLABLE
 static void generate_formatted_string_db (Lisp_Object format_str,
 					  Lisp_Object result_str,
 					  struct window *w,
@@ -261,6 +262,20 @@
 					 Lisp_Object elt,
 					 int depth, int max_pixsize,
 					 face_index findex, int type);
+#else /* MODELINE_IS_SCROLLABLE */
+static void generate_formatted_string_db (Lisp_Object format_str,
+					  Lisp_Object result_str,
+					  struct window *w,
+					  struct display_line *dl,
+					  struct display_block *db,
+					  face_index findex, int min_pixpos,
+					  int max_pixpos, int type);
+static Charcount generate_fstring_runes (struct window *w, pos_data *data,
+					 Charcount pos, Charcount min_pos,
+					 Charcount max_pos, Lisp_Object elt,
+					 int depth, int max_pixsize,
+					 face_index findex, int type);
+#endif /* not MODELINE_IS_SCROLLABLE */
 static prop_block_dynarr *add_emchar_rune (pos_data *data);
 static prop_block_dynarr *add_bufbyte_string_runes (pos_data *data,
 						    Bufbyte *c_string,
@@ -1907,15 +1922,10 @@
     end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
   data.max_pixpos -= end_glyph_width;
 
-  if (cursor_in_echo_area)
-    {
-      if (MINI_WINDOW_P (w) && echo_area_active (f))
-	{
-	  data.bi_cursor_bufpos = BI_BUF_ZV (b);
-	  data.cursor_type = CURSOR_ON;
-	}
-      else
-	data.cursor_type = NO_CURSOR;
+  if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
+    {
+      data.bi_cursor_bufpos = BI_BUF_ZV (b);
+      data.cursor_type = CURSOR_ON;
     }
   else if (MINI_WINDOW_P (w) && !active_minibuffer)
     data.cursor_type = NO_CURSOR;
@@ -3565,17 +3575,26 @@
   else
     ypos_adj = 0;
 
+#ifdef MODELINE_IS_SCROLLABLE
   generate_formatted_string_db (b->modeline_format,
 				b->generated_modeline_string, w, dl, db,
 				MODELINE_INDEX, min_pixpos, max_pixpos, type,
 				1 /* generate a modeline */);
-  
+#else
+  generate_formatted_string_db (b->modeline_format,
+                                b->generated_modeline_string, w, dl, db,
+                                MODELINE_INDEX, min_pixpos, max_pixpos, type);
+#endif /* not MODELINE_IS_SCROLLABLE */
+
   /* The modeline is at the bottom of the gutters.  We have to wait to
      set this until we've generated teh modeline in order to account
      for any embedded faces. */
   dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
 }
 
+/* This define is for the experimental horizontal modeline scrolling. It's not
+   functionnal for 20.5, but might be for 21.1 */
+#ifdef MODELINE_IS_SCROLLABLE
 static void
 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
 			      struct window *w, struct display_line *dl,
@@ -3716,9 +3735,9 @@
 	    INC_CHARPTR (cur_pos);
 	  pos += 1;
 	}
-      else /* Maybe add something */
-	{
-	  if (*cur_pos)
+      else /* pos > 0, things will be visible */
+	{
+	  if (*cur_pos) /* some stuff to add */
 	    {
 	      CONST Bufbyte *old_cur_pos = cur_pos;
 	      int succeeded;
@@ -3733,11 +3752,15 @@
 		  data->bytepos += cur_pos - old_cur_pos;
 		}
 	    }
+	  /* no characters to add */
+	  /* If there 's room enough, add space */
 	  else if (data->pixpos + data->blank_width <= data->max_pixpos)
 	    {
 	      add_blank_rune (data, NULL, 0);
+	      pos += 1;
 	    }
-	  else /* pretend to add something */
+	  /* otherwise, just pretend we added something */
+	  else
 	    {
 	      if (*cur_pos)
 		INC_CHARPTR (cur_pos);
@@ -4014,6 +4037,7 @@
 		max_pos = pos - lim;
 	      else
 		max_pos = min (max_pos, pos - lim);
+	      no_limit = 0;
 	    }
           else if (lim > 0)
             {
@@ -4030,7 +4054,6 @@
               if (lim > min_pos)
                 min_pos = lim;
             }
-	  no_limit = 0;
           goto tail_recurse;
         }
       else if (STRINGP (car) || CONSP (car))
@@ -4112,6 +4135,500 @@
 
   return pos;
 }
+#else /* MODELINE_IS_SCROLLABLE */
+static void
+generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
+                              struct window *w, struct display_line *dl,
+                              struct display_block *db, face_index findex,
+                              int min_pixpos, int max_pixpos, int type)
+{
+  struct frame *f = XFRAME (w->frame);
+  struct device *d = XDEVICE (f->device);
+
+  pos_data data;
+  int c_pixpos;
+
+  memset (&data, 0, sizeof (data));
+  data.d = d;
+  data.db = db;
+  data.dl = dl;
+  data.findex = findex;
+  data.pixpos = min_pixpos;
+  data.max_pixpos = max_pixpos;
+  data.cursor_type = NO_CURSOR;
+  data.last_charset = Qunbound;
+  data.last_findex = DEFAULT_INDEX;
+  data.result_str = result_str;
+  data.is_modeline = 1;
+  XSETWINDOW (data.window, w);
+
+  Dynarr_reset (formatted_string_extent_dynarr);
+  Dynarr_reset (formatted_string_extent_start_dynarr);
+  Dynarr_reset (formatted_string_extent_end_dynarr);
+
+  /* This recursively builds up the modeline. */
+  generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
+                          max_pixpos - min_pixpos, findex, type);
+
+  if (Dynarr_length (db->runes))
+    {
+      struct rune *rb =
+        Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
+      c_pixpos = rb->xpos + rb->width;
+    }
+  else
+    c_pixpos = min_pixpos;
+
+  /* If we don't reach the right side of the window, add a blank rune
+     to make up the difference.  This usually only occurs if the
+     modeline face is using a proportional width font or a fixed width
+     font of a different size from the default face font. */
+
+  if (c_pixpos < max_pixpos)
+    {
+      data.pixpos = c_pixpos;
+      data.blank_width = max_pixpos - data.pixpos;
+
+      add_blank_rune (&data, NULL, 0);
+    }
+
+  /* Now create the result string and frob the extents into it. */
+  if (!NILP (result_str))
+    {
+      int elt;
+      Bytecount len;
+      Bufbyte *strdata;
+      struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
+
+      detach_all_extents (result_str);
+      resize_string (XSTRING (result_str), -1,
+                     data.bytepos - XSTRING_LENGTH (result_str));
+
+      strdata = XSTRING_DATA (result_str);
+
+      for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
+        {
+          if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
+            {
+              len += (set_charptr_emchar
+                      (strdata + len, Dynarr_atp (db->runes,
+                                                  elt)->object.chr.ch));
+            }
+        }
+
+      for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
+           elt++)
+        {
+          Lisp_Object extent = Qnil;
+          Lisp_Object child;
+
+          XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
+          child = Fgethash (extent, buf->modeline_extent_table, Qnil);
+          if (NILP (child))
+            {
+              child = Fmake_extent (Qnil, Qnil, result_str);
+              Fputhash (extent, child, buf->modeline_extent_table);
+            }
+          Fset_extent_parent (child, extent);
+          set_extent_endpoints
+            (XEXTENT (child),
+             Dynarr_at (formatted_string_extent_start_dynarr, elt),
+             Dynarr_at (formatted_string_extent_end_dynarr, elt),
+             result_str);
+        }
+    }
+}
+
+static Charcount
+add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
+                                Charcount pos, Charcount min_pos, Charcount max_pos)
+{
+  /* This function has been Mule-ized. */
+  Charcount end;
+  CONST Bufbyte *cur_pos = str;
+  struct display_block *db = data->db;
+
+  data->blank_width = space_width (XWINDOW (data->window));
+  while (Dynarr_length (db->runes) < pos)
+    add_blank_rune (data, NULL, 0);
+
+  end = (Dynarr_length (db->runes) +
+         bytecount_to_charcount (str, strlen ((CONST char *) str)));
+  if (max_pos != -1)
+    end = min (max_pos, end);
+
+  while (pos < end && *cur_pos)
+    {
+      CONST Bufbyte *old_cur_pos = cur_pos;
+      int succeeded;
+
+      data->ch = charptr_emchar (cur_pos);
+      succeeded = (add_emchar_rune (data) != ADD_FAILED);
+      INC_CHARPTR (cur_pos);
+      if (succeeded)
+        {
+          pos++;
+          data->modeline_charpos++;
+          data->bytepos += cur_pos - old_cur_pos;
+        }
+    }
+
+  while (Dynarr_length (db->runes) < min_pos &&
+         (data->pixpos + data->blank_width <= data->max_pixpos))
+    add_blank_rune (data, NULL, 0);
+
+  return Dynarr_length (db->runes);
+}
+
+/* #### Urk!  Should also handle begin-glyphs and end-glyphs in
+   modeline extents. */
+static Charcount
+add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
+                               Charcount pos, Charcount min_pos, Charcount max_pos)
+{
+  /* This function has been Mule-ized. */
+  Charcount end;
+  struct display_block *db = data->db;
+  struct glyph_block gb;
+
+  data->blank_width = space_width (XWINDOW (data->window));
+  while (Dynarr_length (db->runes) < pos)
+    add_blank_rune (data, NULL, 0);
+
+  end = Dynarr_length (db->runes) + 1;
+  if (max_pos != -1)
+    end = min (max_pos, end);
+
+  gb.glyph = glyph;
+  gb.extent = Qnil;
+  add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
+  pos++;
+
+  while (Dynarr_length (db->runes) < pos &&
+         (data->pixpos + data->blank_width <= data->max_pixpos))
+    add_blank_rune (data, NULL, 0);
+
+  return Dynarr_length (db->runes);
+}
+
+/* If max_pos is == -1, it is considered to be infinite.  The same is
+   true of max_pixsize. */
+#define SET_CURRENT_MODE_CHARS_PIXSIZE                                  \
+  if (Dynarr_length (data->db->runes))                                  \
+    cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
+  else                                                                  \
+    cur_pixsize = 0;
+
+/* Note that this function does "positions" in terms of characters and
+   not in terms of columns.  This is necessary to make the formatting
+   work correctly when proportional width fonts are used in the
+   modeline. */
+static Charcount
+generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
+                        Charcount min_pos, Charcount max_pos,
+                        Lisp_Object elt, int depth, int max_pixsize,
+                        face_index findex, int type)
+{
+  /* This function has been Mule-ized. */
+  /* #### The other losing things in this function are:
+
+     -- C zero-terminated-string lossage.
+     -- Non-printable characters should be converted into something
+        appropriate (e.g. ^F) instead of blindly being printed anyway.
+   */
+
+tail_recurse:
+  if (depth > 10)
+    goto invalid;
+
+  depth++;
+
+  if (STRINGP (elt))
+    {
+      /* A string.  Add to the display line and check for %-constructs
+         within it. */
+
+      Bufbyte *this = XSTRING_DATA (elt);
+
+      while ((pos < max_pos || max_pos == -1) && *this)
+        {
+          Bufbyte *last = this;
+
+          while (*this && *this != '%')
+            this++;
+
+          if (this != last)
+            {
+              /* The string is just a string. */
+              Charcount size =
+                bytecount_to_charcount (last, this - last) + pos;
+              Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos));
+
+              pos = add_string_to_fstring_db_runes (data, last, pos, pos,
+                                                    tmp_max);
+            }
+          else /* *this == '%' */
+            {
+              Charcount spec_width = 0;
+
+              this++; /* skip over '%' */
+
+              /* We can't allow -ve args due to the "%-" construct.
+               * Argument specifies minwidth but not maxwidth
+               * (maxwidth can be specified by
+               * (<negative-number> . <stuff>) modeline elements)
+               */
+              while (isdigit (*this))
+                {
+                  spec_width = spec_width * 10 + (*this - '0');
+                  this++;
+                }
+              spec_width += pos;
+
+              if (*this == 'M')
+                {
+                  pos = generate_fstring_runes (w, data, pos, spec_width,
+                                                max_pos, Vglobal_mode_string,
+                                                depth, max_pixsize, findex,
+                                                type);
+                }
+              else if (*this == '-')
+                {
+                  Charcount num_to_add;
+
+                  if (max_pixsize < 0)
+                    num_to_add = 0;
+                  else if (max_pos != -1)
+                    num_to_add = max_pos - pos;
+                  else
+                    {
+                      int cur_pixsize;
+                      int dash_pixsize;
+                      Bufbyte ch = '-';
+                      SET_CURRENT_MODE_CHARS_PIXSIZE;
+
+                      dash_pixsize =
+                        redisplay_text_width_string (w, findex, &ch, Qnil, 0,
+                                                     1);
+
+                      num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
+                      num_to_add++;
+                    }
+
+                  while (num_to_add--)
+                    pos = add_string_to_fstring_db_runes
+                      (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
+                }
+              else if (*this != 0)
+                {
+                  Bufbyte *str;
+                  Emchar ch = charptr_emchar (this);
+                  decode_mode_spec (w, ch, type);
+
+                  str = Dynarr_atp (mode_spec_bufbyte_string, 0);
+                  pos = add_string_to_fstring_db_runes (data,str, pos, pos,
+                                                        max_pos);
+                }
+
+              /* NOT this++.  There could be any sort of character at
+                 the current position. */
+              INC_CHARPTR (this);
+            }
+
+          if (max_pixsize > 0)
+            {
+              int cur_pixsize;
+              SET_CURRENT_MODE_CHARS_PIXSIZE;
+
+              if (cur_pixsize >= max_pixsize)
+                break;
+            }
+        }
+    }
+  else if (SYMBOLP (elt))
+    {
+      /* A symbol: process the value of the symbol recursively
+         as if it appeared here directly. */
+      Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
+
+      if (!UNBOUNDP (tem))
+        {
+          /* If value is a string, output that string literally:
+             don't check for % within it.  */
+          if (STRINGP (tem))
+            {
+              pos =
+                add_string_to_fstring_db_runes
+                (data, XSTRING_DATA (tem), pos, min_pos, max_pos);
+            }
+          /* Give up right away for nil or t.  */
+          else if (!EQ (tem, elt))
+            {
+              elt = tem;
+              goto tail_recurse;
+            }
+        }
+    }
+  else if (CONSP (elt))
+    {
+      /* A cons cell: four distinct cases.
+       * If first element is a string or a cons, process all the elements
+       * and effectively concatenate them.
+       * If first element is a negative number, truncate displaying cdr to
+       * at most that many characters.  If positive, pad (with spaces)
+       * to at least that many characters.
+       * If first element is a symbol, process the cadr or caddr recursively
+       * according to whether the symbol's value is non-nil or nil.
+       * If first element is a face, process the cdr recursively
+       * without altering the depth.
+       */
+      Lisp_Object car, tem;
+
+      car = XCAR (elt);
+      if (SYMBOLP (car))
+        {
+          elt = XCDR (elt);
+          if (!CONSP (elt))
+            goto invalid;
+          tem = symbol_value_in_buffer (car, w->buffer);
+          /* elt is now the cdr, and we know it is a cons cell.
+             Use its car if CAR has a non-nil value.  */
+          if (!UNBOUNDP (tem))
+            {
+              if (!NILP (tem))
+                {
+                  elt = XCAR (elt);
+                  goto tail_recurse;
+                }
+            }
+          /* Symbol's value is nil (or symbol is unbound)
+           * Get the cddr of the original list
+           * and if possible find the caddr and use that.
+           */
+          elt = XCDR (elt);
+          if (NILP (elt))
+            ;
+          else if (!CONSP (elt))
+            goto invalid;
+          else
+            {
+              elt = XCAR (elt);
+              goto tail_recurse;
+            }
+        }
+      else if (INTP (car))
+        {
+          Charcount lim = XINT (car);
+
+          elt = XCDR (elt);
+
+          if (lim < 0)
+            {
+              /* Negative int means reduce maximum width.
+               * DO NOT change MIN_PIXPOS here!
+               * (20 -10 . foo) should truncate foo to 10 col
+               * and then pad to 20.
+               */
+              if (max_pos == -1)
+                max_pos = pos - lim;
+              else
+                max_pos = min (max_pos, pos - lim);
+            }
+          else if (lim > 0)
+            {
+              /* Padding specified.  Don't let it be more than
+               * current maximum.
+               */
+              lim += pos;
+              if (max_pos != -1 && lim > max_pos)
+                lim = max_pos;
+              /* If that's more padding than already wanted, queue it.
+               * But don't reduce padding already specified even if
+               * that is beyond the current truncation point.
+               */
+              if (lim > min_pos)
+                min_pos = lim;
+            }
+          goto tail_recurse;
+        }
+      else if (STRINGP (car) || CONSP (car))
+        {
+          int limit = 50;
+          /* LIMIT is to protect against circular lists.  */
+          while (CONSP (elt) && --limit > 0
+                 && (pos < max_pos || max_pos == -1))
+            {
+              pos = generate_fstring_runes (w, data, pos, pos, max_pos,
+                                            XCAR (elt), depth,
+                                            max_pixsize, findex, type);
+              elt = XCDR (elt);
+            }
+        }
+      else if (EXTENTP (car))
+        {
+          struct extent *ext = XEXTENT (car);
+
+          if (EXTENT_LIVE_P (ext))
+            {
+              face_index old_findex = data->findex;
+              Lisp_Object face;
+              Lisp_Object font_inst;
+              face_index new_findex;
+              Bytecount start = data->bytepos;
+
+              face = extent_face (ext);
+              if (FACEP (face))
+                {
+                  /* #### needs to merge faces, sigh */
+                  /* #### needs to handle list of faces */
+                  new_findex = get_builtin_face_cache_index (w, face);
+                  /* !!#### not right; needs to compute the max height of
+                     all the charsets */
+                  font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
+                                                       Vcharset_ascii);
+
+                  data->dl->ascent = max (data->dl->ascent,
+                                          XFONT_INSTANCE (font_inst)->ascent);
+                  data->dl->descent = max (data->dl->descent,
+                                           XFONT_INSTANCE (font_inst)->
+                                           descent);
+                }
+              else
+                new_findex = old_findex;
+
+              data->findex = new_findex;
+              pos = generate_fstring_runes (w, data, pos, pos, max_pos,
+                                            XCDR (elt), depth - 1,
+                                            max_pixsize, new_findex, type);
+              data->findex = old_findex;
+              Dynarr_add (formatted_string_extent_dynarr, ext);
+              Dynarr_add (formatted_string_extent_start_dynarr, start);
+              Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
+            }
+        }
+    }
+  else if (GLYPHP (elt))
+    {
+      pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos);
+    }
+  else
+    {
+    invalid:
+      pos =
+        add_string_to_fstring_db_runes
+          (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos,
+           max_pos);
+    }
+
+  if (min_pos > pos)
+    {
+      add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos,
+                                      -1);
+    }
+
+  return pos;
+}
+#endif /* not MODELINE_IS_SCROLLABLE */
 
 /* The caller is responsible for freeing the returned string. */
 Bufbyte *
@@ -4126,11 +4643,16 @@
   db = get_display_block_from_line (dl, TEXT);
   Dynarr_reset (db->runes);
 
+#ifdef MODELINE_IS_SCROLLABLE
   /* D. Verna Feb. 1998.
      Currently, only update_frame_title can make us come here. This is not 
      to build a modeline */
   generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
 				-1, type, 0 /* not a modeline */);
+#else /* not MODELINE_IS_SCROLLABLE */
+  generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
+                                -1, type);
+#endif /* not MODELINE_IS_SCROLLABLE */
 
   Dynarr_reset (formatted_string_emchar_dynarr);
   while (elt < Dynarr_length (db->runes))
@@ -5908,11 +6430,8 @@
 
       /* indicate TEXT or BINARY */
     case 't':
-#ifdef DOS_NT
-      str = NILP (b->buffer_file_type) ? "T" : "B";
-#else /* not DOS_NT */
+      /* #### NT does not use this any more. Now what? */
       str = "T";
-#endif /* not DOS_NT */
       break;
 
       /* print percent of buffer above top of window, or Top, Bot or All */