*** empty log message ***
[dana/urxvt.git] / src / misc.C
index 7144156..e93dba7 100644 (file)
 #include "rxvt.h"              /* NECESSARY */
 #include "misc.intpro"         /* PROTOS for internal routines */
 
-/* EXTPROTO */
 char *
 rxvt_wcstombs (const wchar_t *str, int len)
 {
+  if (len < 0) len = wcslen (str);
+
   mbstate mbs;
   char *r = (char *)rxvt_malloc (len * MB_CUR_MAX + 1);
 
@@ -49,18 +50,128 @@ rxvt_wcstombs (const wchar_t *str, int len)
   return r;
 }
 
-/* EXTPROTO */
+wchar_t *
+rxvt_mbstowcs (const char *str, int len)
+{
+  if (len < 0) len = strlen (str);
+
+  wchar_t *r = (wchar_t *)rxvt_malloc ((len + 1) * sizeof (wchar_t));
+
+  if (mbstowcs (r, str, len + 1) < 0)
+    *r = 0;
+
+  return r;
+}
+
+char *
+rxvt_wcstoutf8 (const wchar_t *str, int len)
+{
+  if (len < 0) len = wcslen (str);
+
+  char *r = (char *)rxvt_malloc (len * 4 + 1);
+  char *p = r;
+
+  while (len--)
+    {
+      unicode_t w = *str++;
+
+      if      (w < 0x000080)
+        *p++ = w;
+      else if (w < 0x000800)
+        *p++ = 0xc0 | ( w >>  6),
+        *p++ = 0x80 | ( w        & 0x3f);
+      else if (w < 0x010000)
+        *p++ = 0xe0 | ( w >> 12       ),
+        *p++ = 0x80 | ((w >>  6) & 0x3f),
+        *p++ = 0x80 | ( w        & 0x3f);
+      else if (w < 0x110000)
+        *p++ = 0xf0 | ( w >> 18),
+        *p++ = 0x80 | ((w >> 12) & 0x3f),
+        *p++ = 0x80 | ((w >>  6) & 0x3f),
+        *p++ = 0x80 | ( w        & 0x3f);
+      else
+        *p++ = '?';
+    }
+
+  *p = 0;
+
+  return r;
+}
+
+wchar_t *
+rxvt_utf8towcs (const char *str, int len)
+{
+  if (len < 0) len = strlen (str);
+
+  wchar_t *r = (wchar_t *)rxvt_malloc ((len + 1) * sizeof (wchar_t));
+  wchar_t *p = r;
+
+  unsigned char *s = (unsigned char *)str;
+
+  while (len)
+    {
+      if (s[0] < 0x80)
+        {
+          *p++ = *s++; len--;
+        }
+      else if (len > 0 
+               && s[0] >= 0xc2 && s[0] <= 0xdf 
+               && (s[1] & 0xc0) == 0x80)
+        {
+          *p++ = ((s[0] & 0x1f) << 6)
+               |  (s[1] & 0x3f);
+          s += 2; len -= 2;
+        }
+      else if (len > 1 
+               && (   (s[0] == 0xe0                 && s[1] >= 0xa0 && s[1] <= 0xbf)
+                   || (s[0] >= 0xe1 && s[0] <= 0xec && s[1] >= 0x80 && s[1] <= 0xbf)
+                   || (s[0] == 0xed                 && s[1] >= 0x80 && s[1] <= 0x9f)
+                   || (s[0] >= 0xee && s[0] <= 0xef && s[1] >= 0x80 && s[1] <= 0xbf)
+                  )
+               && (s[2] & 0xc0) == 0x80)
+        {
+          *p++ = ((s[0] & 0x0f) << 12)
+               | ((s[1] & 0x3f) <<  6)
+               |  (s[2] & 0x3f);
+          s += 3; len -= 3;
+        }
+      else if (len > 2
+               && (   (s[0] == 0xf0                 && s[1] >= 0x90 && s[1] <= 0xbf)
+                   || (s[0] >= 0xf1 && s[0] <= 0xf3 && s[1] >= 0x80 && s[1] <= 0xbf)
+                   || (s[0] == 0xf4                 && s[1] >= 0x80 && s[1] <= 0x8f)
+                  )
+               && (s[2] & 0xc0) == 0x80
+               && (s[3] & 0xc0) == 0x80)
+        {
+          *p++ = ((s[0] & 0x07) << 18) 
+               | ((s[1] & 0x3f) << 12) 
+               | ((s[2] & 0x3f) <<  6) 
+               |  (s[3] & 0x3f);
+          s += 4; len -= 4;
+        }
+      else
+        {
+          *p++ = 0xfffd;
+          s++; len--;
+        }
+    }
+
+  *p = 0;
+
+  return r;
+}
+
 char *
 rxvt_strdup (const char *str)
 {
   return str ? strdup (str) : 0;
 }
 
-/* EXTPROTO */
+/* INTPROTO */
 char *
 rxvt_r_basename (const char *str)
 {
-  char *base = STRRCHR (str, '/');
+  char *base = strrchr (str, '/');
 
   return (char *) (base ? base + 1 : str);
 }
@@ -68,7 +179,7 @@ rxvt_r_basename (const char *str)
 /*
  * Print an error message
  */
-/* EXTPROTO */
+/* INTPROTO */
 void
 rxvt_vlog (const char *fmt, va_list arg_ptr)
 {
@@ -82,7 +193,7 @@ rxvt_vlog (const char *fmt, va_list arg_ptr)
     write (STDOUT_FILENO, msg, strlen (msg));
 }
 
-/* EXTPROTO */
+/* INTPROTO */
 void
 rxvt_log (const char *fmt,...)
 {
@@ -96,7 +207,7 @@ rxvt_log (const char *fmt,...)
 /*
  * Print an error message
  */
-/* EXTPROTO */
+/* INTPROTO */
 void
 rxvt_warn (const char *fmt,...)
 {
@@ -109,7 +220,7 @@ rxvt_warn (const char *fmt,...)
   va_end (arg_ptr);
 }
 
-/* EXTPROTO */
+/* INTPROTO */
 void
 rxvt_fatal (const char *fmt,...)
 {
@@ -126,7 +237,7 @@ rxvt_fatal (const char *fmt,...)
 
 class rxvt_failure_exception rxvt_failure_exception;
 
-/* EXTPROTO */
+/* INTPROTO */
 void
 rxvt_exit_failure ()
 {
@@ -139,18 +250,18 @@ rxvt_exit_failure ()
  * No Match
  *      return: 0
  * Match
- *      return: STRLEN (S2)
+ *      return: strlen (S2)
  */
-/* EXTPROTO */
+/* INTPROTO */
 int
 rxvt_Str_match (const char *s1, const char *s2)
 {
-  int n = STRLEN (s2);
+  int n = strlen (s2);
 
-  return ((STRNCMP (s1, s2, n) == 0) ? n : 0);
+  return ((strncmp (s1, s2, n) == 0) ? n : 0);
 }
 
-/* EXTPROTO */
+/* INTPROTO */
 const char *
 rxvt_Str_skip_space (const char *str)
 {
@@ -165,7 +276,7 @@ rxvt_Str_skip_space (const char *str)
  * remove leading/trailing space and strip-off leading/trailing quotes.
  * in place.
  */
-/* EXTPROTO */
+/* INTPROTO */
 char           *
 rxvt_Str_trim (char *str)
 {
@@ -214,7 +325,7 @@ rxvt_Str_trim (char *str)
  *
  * returns the converted string length
  */
-/* EXTPROTO */
+/* INTPROTO */
 int
 rxvt_Str_escaped (char *str)
 {
@@ -292,7 +403,7 @@ rxvt_Str_escaped (char *str)
  * are properly returned
  * Caller should free each entry and array when done
  */
-/* EXTPROTO */
+/* INTPROTO */
 char          **
 rxvt_splitcommastring (const char *cs)
 {
@@ -322,6 +433,15 @@ rxvt_splitcommastring (const char *cs)
   return ret;
 }
 
+void
+rxvt_freecommastring (char **cs)
+{
+  for (int i = 0; cs[i]; ++i)
+    free (cs[i]);
+
+  free (cs);
+}
+
 /*----------------------------------------------------------------------*
  * file searching
  */
@@ -344,13 +464,13 @@ rxvt_File_search_path (const char *pathlist, const char *file, const char *ext)
   char            name[256];
 
   if (!access (file, R_OK))    /* found (plain name) in current directory */
-    return STRDUP (file);
+    return strdup (file);
 
   /* semi-colon delimited */
-  if ((p = STRCHR (file, ';')))
+  if ((p = strchr (file, ';')))
     len = (p - file);
   else
-    len = STRLEN (file);
+    len = strlen (file);
 
 #ifdef DEBUG_SEARCH_PATH
   getcwd (name, sizeof (name));
@@ -359,29 +479,29 @@ rxvt_File_search_path (const char *pathlist, const char *file, const char *ext)
 #endif
 
   /* leave room for an extra '/' and trailing '\0' */
-  maxpath = sizeof (name) - (len + (ext ? STRLEN (ext) : 0) + 2);
+  maxpath = sizeof (name) - (len + (ext ? strlen (ext) : 0) + 2);
   if (maxpath <= 0)
     return NULL;
 
   /* check if we can find it now */
-  STRNCPY (name, file, len);
+  strncpy (name, file, len);
   name[len] = '\0';
 
   if (!access (name, R_OK))
-    return STRDUP (name);
+    return strdup (name);
   if (ext)
     {
-      STRCAT (name, ext);
+      strcat (name, ext);
       if (!access (name, R_OK))
-        return STRDUP (name);
+        return strdup (name);
     }
   for (path = pathlist; path != NULL && *path != '\0'; path = p)
     {
       int             n;
 
       /* colon delimited */
-      if ((p = STRCHR (path, ':')) == NULL)
-        p = STRCHR (path, '\0');
+      if ((p = strchr (path, ':')) == NULL)
+        p = strchr (path, '\0');
 
       n = (p - path);
       if (*p != '\0')
@@ -389,26 +509,26 @@ rxvt_File_search_path (const char *pathlist, const char *file, const char *ext)
 
       if (n > 0 && n <= maxpath)
         {
-          STRNCPY (name, path, n);
+          strncpy (name, path, n);
           if (name[n - 1] != '/')
             name[n++] = '/';
           name[n] = '\0';
-          STRNCAT (name, file, len);
+          strncat (name, file, len);
 
           if (!access (name, R_OK))
-            return STRDUP (name);
+            return strdup (name);
           if (ext)
             {
-              STRCAT (name, ext);
+              strcat (name, ext);
               if (!access (name, R_OK))
-                return STRDUP (name);
+                return strdup (name);
             }
         }
     }
   return NULL;
 }
 
-/* EXTPROTO */
+/* INTPROTO */
 char           *
 rxvt_File_find (const char *file, const char *ext, const char *path)
 {
@@ -441,7 +561,7 @@ rxvt_File_find (const char *file, const char *ext, const char *path)
  * Draw top/left and bottom/right border shadows around windows
  */
 #if defined(RXVT_SCROLLBAR) || defined(MENUBAR)
-/* EXTPROTO */
+/* INTPROTO */
 void
 rxvt_Draw_Shadow (Display *display, Window win, GC topShadow, GC botShadow, int x, int y, int w, int h)
 {
@@ -462,7 +582,7 @@ rxvt_Draw_Shadow (Display *display, Window win, GC topShadow, GC botShadow, int
 
 /* button shapes */
 #ifdef MENUBAR
-/* EXTPROTO */
+/* INTPROTO */
 void
 rxvt_Draw_Triangle (Display *display, Window win, GC topShadow, GC botShadow, int x, int y, int w, int type)
 {