/[emacs]/emacs/src/editfns.c
ViewVC logotype

Diff of /emacs/src/editfns.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.353 by handa, Fri Apr 4 10:47:15 2003 UTC revision 1.354 by rms, Wed Apr 9 01:28:44 2003 UTC
# Line 3201  usage: (format STRING &rest OBJECTS)  */ Line 3201  usage: (format STRING &rest OBJECTS)  */
3201    register int n;               /* The number of the next arg to substitute */    register int n;               /* The number of the next arg to substitute */
3202    register int total;           /* An estimate of the final length */    register int total;           /* An estimate of the final length */
3203    char *buf, *p;    char *buf, *p;
3204    register unsigned char *format, *end;    register unsigned char *format, *end, *format_start;
3205    int nchars;    int nchars;
3206    /* Nonzero if the output should be a multibyte string,    /* Nonzero if the output should be a multibyte string,
3207       which is true if any of the inputs is one.  */       which is true if any of the inputs is one.  */
# Line 3220  usage: (format STRING &rest OBJECTS)  */ Line 3220  usage: (format STRING &rest OBJECTS)  */
3220    int *precision = (int *) (alloca(nargs * sizeof (int)));    int *precision = (int *) (alloca(nargs * sizeof (int)));
3221    int longest_format;    int longest_format;
3222    Lisp_Object val;    Lisp_Object val;
3223      int arg_intervals = 0;
3224    
3225      /* discarded[I] is 1 if byte I of the format
3226         string was not copied into the output.
3227         It is 2 if byte I was not the first byte of its character.  */
3228      char *discarded;
3229    
3230      /* Each element records, for one argument,
3231         the start and end bytepos in the output string,
3232         and whether the argument is a string with intervals.
3233         info[0] is unused.  Unused elements have -1 for start.  */
3234    struct info    struct info
3235    {    {
3236      int start, end;      int start, end, intervals;
3237    } *info = 0;    } *info = 0;
3238    
3239    /* It should not be necessary to GCPRO ARGS, because    /* It should not be necessary to GCPRO ARGS, because
# Line 3232  usage: (format STRING &rest OBJECTS)  */ Line 3243  usage: (format STRING &rest OBJECTS)  */
3243       This is not always right; sometimes the result needs to be multibyte       This is not always right; sometimes the result needs to be multibyte
3244       because of an object that we will pass through prin1,       because of an object that we will pass through prin1,
3245       and in that case, we won't know it here.  */       and in that case, we won't know it here.  */
3246    for (n = 0; n < nargs; n++) {    for (n = 0; n < nargs; n++)
3247      if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))      {
3248        multibyte = 1;        if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
3249      /* Piggyback on this loop to initialize precision[N]. */          multibyte = 1;
3250      precision[n] = -1;        /* Piggyback on this loop to initialize precision[N]. */
3251    }        precision[n] = -1;
3252        }
3253    
3254    CHECK_STRING (args[0]);    CHECK_STRING (args[0]);
3255    /* We may have to change "%S" to "%s". */    /* We may have to change "%S" to "%s". */
# Line 3248  usage: (format STRING &rest OBJECTS)  */ Line 3260  usage: (format STRING &rest OBJECTS)  */
3260   retry:   retry:
3261    
3262    format = SDATA (args[0]);    format = SDATA (args[0]);
3263      format_start = format;
3264    end = format + SBYTES (args[0]);    end = format + SBYTES (args[0]);
3265    longest_format = 0;    longest_format = 0;
3266    
3267    /* Make room in result for all the non-%-codes in the control string.  */    /* Make room in result for all the non-%-codes in the control string.  */
3268    total = 5 + CONVERTED_BYTE_SIZE (multibyte, args[0]);    total = 5 + CONVERTED_BYTE_SIZE (multibyte, args[0]);
3269    
3270      /* Allocate the info and discarded tables.  */
3271      {
3272        int nbytes = nargs * sizeof *info;
3273        int i;
3274        info = (struct info *) alloca (nbytes);
3275        bzero (info, nbytes);
3276        for (i = 0; i <= nargs; i++)
3277          info[i].start = -1;
3278        discarded = (char *) alloca (SBYTES (args[0]));
3279        bzero (discarded, SBYTES (args[0]));
3280      }
3281    
3282    /* Add to TOTAL enough space to hold the converted arguments.  */    /* Add to TOTAL enough space to hold the converted arguments.  */
3283    
3284    n = 0;    n = 0;
# Line 3458  usage: (format STRING &rest OBJECTS)  */ Line 3483  usage: (format STRING &rest OBJECTS)  */
3483            int negative = 0;            int negative = 0;
3484            unsigned char *this_format_start = format;            unsigned char *this_format_start = format;
3485    
3486              discarded[format - format_start] = 1;
3487            format++;            format++;
3488    
3489            /* Process a numeric arg and skip it.  */            /* Process a numeric arg and skip it.  */
# Line 3471  usage: (format STRING &rest OBJECTS)  */ Line 3497  usage: (format STRING &rest OBJECTS)  */
3497               fixed. */               fixed. */
3498            while ((*format >= '0' && *format <= '9')            while ((*format >= '0' && *format <= '9')
3499                   || *format == '-' || *format == ' ' || *format == '.')                   || *format == '-' || *format == ' ' || *format == '.')
3500              format++;              {
3501                  discarded[format - format_start] = 1;
3502                  format++;
3503                }
3504    
3505            if (*format++ == '%')            if (*format++ == '%')
3506              {              {
# Line 3482  usage: (format STRING &rest OBJECTS)  */ Line 3511  usage: (format STRING &rest OBJECTS)  */
3511    
3512            ++n;            ++n;
3513    
3514              discarded[format - format_start - 1] = 1;
3515              info[n].start = nchars;
3516    
3517            if (STRINGP (args[n]))            if (STRINGP (args[n]))
3518              {              {
3519                /* handle case (precision[n] >= 0) */                /* handle case (precision[n] >= 0) */
# Line 3541  usage: (format STRING &rest OBJECTS)  */ Line 3573  usage: (format STRING &rest OBJECTS)  */
3573                /* If this argument has text properties, record where                /* If this argument has text properties, record where
3574                   in the result string it appears.  */                   in the result string it appears.  */
3575                if (STRING_INTERVALS (args[n]))                if (STRING_INTERVALS (args[n]))
3576                  {                  info[n].intervals = arg_intervals = 1;
                   if (!info)  
                     {  
                       int nbytes = nargs * sizeof *info;  
                       info = (struct info *) alloca (nbytes);  
                       bzero (info, nbytes);  
                     }  
   
                   info[n].start = start;  
                   info[n].end = end;  
                 }  
3577              }              }
3578            else if (INTEGERP (args[n]) || FLOATP (args[n]))            else if (INTEGERP (args[n]) || FLOATP (args[n]))
3579              {              {
# Line 3578  usage: (format STRING &rest OBJECTS)  */ Line 3600  usage: (format STRING &rest OBJECTS)  */
3600                  p += this_nchars;                  p += this_nchars;
3601                nchars += this_nchars;                nchars += this_nchars;
3602              }              }
3603    
3604              info[n].end = nchars;
3605          }          }
3606        else if (STRING_MULTIBYTE (args[0]))        else if (STRING_MULTIBYTE (args[0]))
3607          {          {
# Line 3588  usage: (format STRING &rest OBJECTS)  */ Line 3612  usage: (format STRING &rest OBJECTS)  */
3612                && !CHAR_HEAD_P (*format))                && !CHAR_HEAD_P (*format))
3613              maybe_combine_byte = 1;              maybe_combine_byte = 1;
3614            *p++ = *format++;            *p++ = *format++;
3615            while (! CHAR_HEAD_P (*format)) *p++ = *format++;            while (! CHAR_HEAD_P (*format))
3616                {
3617                  discarded[format - format_start] = 2;
3618                  *p++ = *format++;
3619                }
3620            nchars++;            nchars++;
3621          }          }
3622        else if (multibyte)        else if (multibyte)
# Line 3619  usage: (format STRING &rest OBJECTS)  */ Line 3647  usage: (format STRING &rest OBJECTS)  */
3647       arguments has text properties, set up text properties of the       arguments has text properties, set up text properties of the
3648       result string.  */       result string.  */
3649    
3650    if (STRING_INTERVALS (args[0]) || info)    if (STRING_INTERVALS (args[0]) || arg_intervals)
3651      {      {
3652        Lisp_Object len, new_len, props;        Lisp_Object len, new_len, props;
3653        struct gcpro gcpro1;        struct gcpro gcpro1;
# Line 3631  usage: (format STRING &rest OBJECTS)  */ Line 3659  usage: (format STRING &rest OBJECTS)  */
3659    
3660        if (CONSP (props))        if (CONSP (props))
3661          {          {
3662            new_len = make_number (SCHARS (val));            int bytepos = 0, position = 0, translated = 0, argn = 1;
3663            extend_property_ranges (props, len, new_len);            Lisp_Object list;
3664    
3665              /* Adjust the bounds of each text property
3666                 to the proper start and end in the output string.  */
3667              /* We take advantage of the fact that the positions in PROPS
3668                 are in increasing order, so that we can do (effectively)
3669                 one scan through the position space of the format string.
3670    
3671                 BYTEPOS is the byte position in the format string,
3672                 POSITION is the untranslated char position in it,
3673                 TRANSLATED is the translated char position in BUF,
3674                 and ARGN is the number of the next arg we will come to.  */
3675              for (list = props; CONSP (list); list = XCDR (list))
3676                {
3677                  Lisp_Object item, pos;
3678    
3679                  item = XCAR (list);
3680    
3681                  /* First adjust the property start position.  */
3682                  pos = XINT (XCAR (item));
3683    
3684                  /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN
3685                     up to this position.  */
3686                  for (; position < pos; bytepos++)
3687                    {
3688                      if (! discarded[bytepos])
3689                        position++, translated++;
3690                      else if (discarded[bytepos] == 1)
3691                        {
3692                          position++;
3693                          if (translated == info[argn].start)
3694                            {
3695                              translated += info[argn].end - info[argn].start;
3696                              argn++;
3697                            }
3698                        }
3699                    }
3700    
3701                  XSETCAR (item, make_number (translated));
3702    
3703                  /* Likewise adjust the property end position.  */
3704                  pos = XINT (XCAR (XCDR (item)));
3705    
3706                  for (; bytepos < pos; bytepos++)
3707                    {
3708                      if (! discarded[bytepos])
3709                        position++, translated++;
3710                      else if (discarded[bytepos] == 1)
3711                        {
3712                          position++;
3713                          if (translated == info[argn].start)
3714                            {
3715                              translated += info[argn].end - info[argn].start;
3716                              argn++;
3717                            }
3718                        }
3719                    }
3720    
3721                  XSETCAR (XCDR (item), make_number (translated));
3722                }
3723    
3724            add_text_properties_from_list (val, props, make_number (0));            add_text_properties_from_list (val, props, make_number (0));
3725          }          }
3726    
3727        /* Add text properties from arguments.  */        /* Add text properties from arguments.  */
3728        if (info)        if (arg_intervals)
3729          for (n = 1; n < nargs; ++n)          for (n = 1; n < nargs; ++n)
3730            if (info[n].end)            if (info[n].intervals)
3731              {              {
3732                len = make_number (SCHARS (args[n]));                len = make_number (SCHARS (args[n]));
3733                new_len = make_number (info[n].end - info[n].start);                new_len = make_number (info[n].end - info[n].start);

Legend:
Removed from v.1.353  
changed lines
  Added in v.1.354

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26