Logo Search packages:      
Sourcecode: alsa-utils version File versions  Download package

utils.c

/*
 * utils.c - multibyte-string helpers
 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#define _XOPEN_SOURCE
#include "aconfig.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "utils.h"

/*
 * mbs_at_width - compute screen position in a string
 *
 * For displaying strings on the screen, we have to know how many character
 * cells are occupied.  This function calculates the position in a multibyte
 * string that is at a desired position.
 *
 * Parameters:
 * s:     the string
 * width: on input, the desired number of character cells; on output, the actual
 *        position, in character cells, of the return value
 * dir:   -1 or 1; in which direction to round if a multi-column character goes
 *        over the desired width
 *
 * Return value:
 * Pointer to the place in the string that is as near the desired width as
 * possible.  If the string is too short, the return value points to the
 * terminating zero.  If the last character is a multi-column character that
 * goes over the desired width, the return value may be one character cell
 * earlier or later than desired, depending on the dir parameter.
 * In any case, the return value points after any zero-width characters that
 * follow the last character.
 */
const char *mbs_at_width(const char *s, int *width, int dir)
{
      size_t len;
      wchar_t wc;
      int bytes;
      int width_so_far, w;

      if (*width <= 0)
            return s;
      mbtowc(NULL, NULL, 0); /* reset shift state */
      len = strlen(s);
      width_so_far = 0;
      while (len && (bytes = mbtowc(&wc, s, len)) > 0) {
            w = wcwidth(wc);
            if (width_so_far + w > *width && dir < 0)
                  break;
            if (w >= 0)
                  width_so_far += w;
            s += bytes;
            len -= bytes;
            if (width_so_far >= *width) {
                  while (len && (bytes = mbtowc(&wc, s, len)) > 0) {
                        w = wcwidth(wc);
                        if (w != 0)
                              break;
                        s += bytes;
                        len -= bytes;
                  }
                  break;
            }
      }
      *width = width_so_far;
      return s;
}

/*
 * get_mbs_width - compute screen width of a string
 */
unsigned int get_mbs_width(const char *s)
{
      int width;

      width = INT_MAX;
      mbs_at_width(s, &width, 1);
      return width;
}

/*
 * get_max_mbs_width - get width of longest string in an array
 */
unsigned int get_max_mbs_width(const char *const *s, unsigned int count)
{
      unsigned int max_width, i, len;

      max_width = 0;
      for (i = 0; i < count; ++i) {
            len = get_mbs_width(s[i]);
            if (len > max_width)
                  max_width = len;
      }
      return max_width;
}

Generated by  Doxygen 1.6.0   Back to index