root/lib/strutil/strutil8bit.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. DECLARE_CTYPE_WRAPPER
  2. str_8bit_is_valid_string
  3. str_8bit_is_valid_char
  4. str_8bit_cnext_char
  5. str_8bit_cprev_char
  6. str_8bit_cnext_noncomb_char
  7. str_8bit_cprev_noncomb_char
  8. str_8bit_isspace
  9. str_8bit_ispunct
  10. str_8bit_isalnum
  11. str_8bit_isdigit
  12. str_8bit_isprint
  13. str_8bit_iscombiningmark
  14. str_8bit_toupper
  15. str_8bit_tolower
  16. str_8bit_length
  17. str_8bit_length2
  18. str_8bit_conv_gerror_message
  19. str_8bit_vfs_convert_to
  20. str_8bit_term_form
  21. str_8bit_fit_to_term
  22. str_8bit_term_trim
  23. str_8bit_term_width2
  24. str_8bit_term_width1
  25. str_8bit_term_char_width
  26. str_8bit_term_substring
  27. str_8bit_trunc
  28. str_8bit_offset_to_pos
  29. str_8bit_column_to_pos
  30. str_8bit_create_search_needle
  31. str_8bit_release_search_needle
  32. str_8bit_strdown
  33. str_8bit_search_first
  34. str_8bit_search_last
  35. str_8bit_compare
  36. str_8bit_ncompare
  37. str_8bit_casecmp
  38. str_8bit_ncasecmp
  39. str_8bit_prefix
  40. str_8bit_caseprefix
  41. str_8bit_fix_string
  42. str_8bit_create_key
  43. str_8bit_key_collate
  44. str_8bit_release_key
  45. str_8bit_init

   1 /*
   2    8bit strings utilities
   3 
   4    Copyright (C) 2007-2019
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Rostislav Benes, 2007
   9 
  10    This file is part of the Midnight Commander.
  11 
  12    The Midnight Commander is free software: you can redistribute it
  13    and/or modify it under the terms of the GNU General Public License as
  14    published by the Free Software Foundation, either version 3 of the License,
  15    or (at your option) any later version.
  16 
  17    The Midnight Commander is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21 
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24  */
  25 
  26 #include <config.h>
  27 
  28 #include <ctype.h>
  29 #include <stdlib.h>
  30 
  31 #include "lib/global.h"
  32 #include "lib/strutil.h"
  33 
  34 /* Functions for singlebyte encodings, all characters have width 1
  35  * using standard system functions.
  36  * There are only small differences between functions in strutil8bit.c
  37  * and strutilascii.c.
  38  */
  39 
  40 /*** global variables ****************************************************************************/
  41 
  42 /*** file scope macro definitions ****************************************************************/
  43 
  44 /*
  45  * Inlines to equalize 'char' signedness for single 'char' encodings.
  46  * Instead of writing
  47  *    isspace ((unsigned char) c);
  48  * you can write
  49  *    char_isspace (c);
  50  */
  51 #define DECLARE_CTYPE_WRAPPER(func_name)       \
  52 static inline int char_##func_name(char c)     \
  53 {                                              \
  54     return func_name((int)(unsigned char)c);   \
  55 }
  56 
  57 /*** file scope type declarations ****************************************************************/
  58 
  59 /*** file scope variables ************************************************************************/
  60 
  61 static const char replch = '?';
  62 
  63 /* --------------------------------------------------------------------------------------------- */
  64 /*** file scope functions ************************************************************************/
  65 /* --------------------------------------------------------------------------------------------- */
  66 
  67 /* *INDENT-OFF* */
  68 DECLARE_CTYPE_WRAPPER (isalnum)
     /* [previous][next][first][last][top][bottom][index][help]  */
  69 DECLARE_CTYPE_WRAPPER (isdigit)
  70 DECLARE_CTYPE_WRAPPER (isprint)
  71 DECLARE_CTYPE_WRAPPER (ispunct)
  72 DECLARE_CTYPE_WRAPPER (isspace)
  73 DECLARE_CTYPE_WRAPPER (toupper)
  74 DECLARE_CTYPE_WRAPPER (tolower)
  75 /* *INDENT-ON* */
  76 
  77 /* --------------------------------------------------------------------------------------------- */
  78 
  79 static void
  80 str_8bit_insert_replace_char (GString * buffer)
  81 {
  82     g_string_append_c (buffer, replch);
  83 }
  84 
  85 /* --------------------------------------------------------------------------------------------- */
  86 
  87 static gboolean
  88 str_8bit_is_valid_string (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
  89 {
  90     (void) text;
  91     return TRUE;
  92 }
  93 
  94 /* --------------------------------------------------------------------------------------------- */
  95 
  96 static int
  97 str_8bit_is_valid_char (const char *ch, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
  98 {
  99     (void) ch;
 100     (void) size;
 101     return 1;
 102 }
 103 
 104 /* --------------------------------------------------------------------------------------------- */
 105 
 106 static void
 107 str_8bit_cnext_char (const char **text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 108 {
 109     (*text)++;
 110 }
 111 
 112 /* --------------------------------------------------------------------------------------------- */
 113 
 114 static void
 115 str_8bit_cprev_char (const char **text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 116 {
 117     (*text)--;
 118 }
 119 
 120 /* --------------------------------------------------------------------------------------------- */
 121 
 122 static int
 123 str_8bit_cnext_noncomb_char (const char **text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 124 {
 125     if (*text[0] == '\0')
 126         return 0;
 127 
 128     (*text)++;
 129     return 1;
 130 }
 131 
 132 /* --------------------------------------------------------------------------------------------- */
 133 
 134 static int
 135 str_8bit_cprev_noncomb_char (const char **text, const char *begin)
     /* [previous][next][first][last][top][bottom][index][help]  */
 136 {
 137     if ((*text) == begin)
 138         return 0;
 139 
 140     (*text)--;
 141     return 1;
 142 }
 143 
 144 /* --------------------------------------------------------------------------------------------- */
 145 
 146 static gboolean
 147 str_8bit_isspace (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 148 {
 149     return char_isspace (text[0]) != 0;
 150 }
 151 
 152 /* --------------------------------------------------------------------------------------------- */
 153 
 154 static gboolean
 155 str_8bit_ispunct (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 156 {
 157     return char_ispunct (text[0]) != 0;
 158 }
 159 
 160 /* --------------------------------------------------------------------------------------------- */
 161 
 162 static gboolean
 163 str_8bit_isalnum (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 164 {
 165     return char_isalnum (text[0]) != 0;
 166 }
 167 
 168 /* --------------------------------------------------------------------------------------------- */
 169 
 170 static gboolean
 171 str_8bit_isdigit (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 172 {
 173     return char_isdigit (text[0]) != 0;
 174 }
 175 
 176 /* --------------------------------------------------------------------------------------------- */
 177 
 178 static gboolean
 179 str_8bit_isprint (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 180 {
 181     return char_isprint (text[0]) != 0;
 182 }
 183 
 184 /* --------------------------------------------------------------------------------------------- */
 185 
 186 static gboolean
 187 str_8bit_iscombiningmark (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 188 {
 189     (void) text;
 190     return FALSE;
 191 }
 192 
 193 /* --------------------------------------------------------------------------------------------- */
 194 
 195 static int
 196 str_8bit_toupper (const char *text, char **out, size_t * remain)
     /* [previous][next][first][last][top][bottom][index][help]  */
 197 {
 198     if (*remain <= 1)
 199         return FALSE;
 200 
 201     (*out)[0] = char_toupper (text[0]);
 202     (*out)++;
 203     (*remain)--;
 204     return TRUE;
 205 }
 206 
 207 /* --------------------------------------------------------------------------------------------- */
 208 
 209 static gboolean
 210 str_8bit_tolower (const char *text, char **out, size_t * remain)
     /* [previous][next][first][last][top][bottom][index][help]  */
 211 {
 212     if (*remain <= 1)
 213         return FALSE;
 214 
 215     (*out)[0] = char_tolower (text[0]);
 216     (*out)++;
 217     (*remain)--;
 218     return TRUE;
 219 }
 220 
 221 /* --------------------------------------------------------------------------------------------- */
 222 
 223 static int
 224 str_8bit_length (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 225 {
 226     return strlen (text);
 227 }
 228 
 229 /* --------------------------------------------------------------------------------------------- */
 230 
 231 static int
 232 str_8bit_length2 (const char *text, int size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 233 {
 234     return (size >= 0) ? MIN (strlen (text), (gsize) size) : strlen (text);
 235 }
 236 
 237 /* --------------------------------------------------------------------------------------------- */
 238 
 239 static gchar *
 240 str_8bit_conv_gerror_message (GError * mcerror, const char *def_msg)
     /* [previous][next][first][last][top][bottom][index][help]  */
 241 {
 242     GIConv conv;
 243     gchar *ret;
 244 
 245     /* glib messages are in UTF-8 charset */
 246     conv = str_crt_conv_from ("UTF-8");
 247 
 248     if (conv == INVALID_CONV)
 249         ret = g_strdup (def_msg != NULL ? def_msg : "");
 250     else
 251     {
 252         GString *buf;
 253 
 254         buf = g_string_new ("");
 255 
 256         if (str_convert (conv, mcerror->message, buf) != ESTR_FAILURE)
 257             ret = g_string_free (buf, FALSE);
 258         else
 259         {
 260             ret = g_strdup (def_msg != NULL ? def_msg : "");
 261             g_string_free (buf, TRUE);
 262         }
 263 
 264         str_close_conv (conv);
 265     }
 266 
 267     return ret;
 268 }
 269 
 270 /* --------------------------------------------------------------------------------------------- */
 271 
 272 static estr_t
 273 str_8bit_vfs_convert_to (GIConv coder, const char *string, int size, GString * buffer)
     /* [previous][next][first][last][top][bottom][index][help]  */
 274 {
 275     estr_t result = ESTR_SUCCESS;
 276 
 277     if (coder == str_cnv_not_convert)
 278         g_string_append_len (buffer, string, size);
 279     else
 280         result = str_nconvert (coder, string, size, buffer);
 281 
 282     return result;
 283 }
 284 
 285 /* --------------------------------------------------------------------------------------------- */
 286 
 287 static const char *
 288 str_8bit_term_form (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 289 {
 290     static char result[BUF_MEDIUM];
 291     char *actual;
 292     size_t remain;
 293     size_t length;
 294     size_t pos = 0;
 295 
 296     actual = result;
 297     remain = sizeof (result);
 298     length = strlen (text);
 299 
 300     for (; pos < length && remain > 1; pos++, actual++, remain--)
 301         actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 302 
 303     actual[0] = '\0';
 304     return result;
 305 }
 306 
 307 /* --------------------------------------------------------------------------------------------- */
 308 
 309 static const char *
 310 str_8bit_fit_to_term (const char *text, int width, align_crt_t just_mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
 311 {
 312     static char result[BUF_MEDIUM];
 313     char *actual;
 314     size_t remain;
 315     int ident = 0;
 316     size_t length;
 317     size_t pos = 0;
 318 
 319     length = strlen (text);
 320     actual = result;
 321     remain = sizeof (result);
 322 
 323     if ((int) length <= width)
 324     {
 325         switch (HIDE_FIT (just_mode))
 326         {
 327         case J_CENTER_LEFT:
 328         case J_CENTER:
 329             ident = (width - length) / 2;
 330             break;
 331         case J_RIGHT:
 332             ident = width - length;
 333             break;
 334         default:
 335             break;
 336         }
 337 
 338         if ((int) remain <= ident)
 339             goto finally;
 340         memset (actual, ' ', ident);
 341         actual += ident;
 342         remain -= ident;
 343 
 344         for (; pos < length && remain > 1; pos++, actual++, remain--)
 345             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 346 
 347         if (width - length - ident > 0)
 348         {
 349             if (remain <= width - length - ident)
 350                 goto finally;
 351             memset (actual, ' ', width - length - ident);
 352             actual += width - length - ident;
 353         }
 354     }
 355     else if (IS_FIT (just_mode))
 356     {
 357         for (; pos + 1 <= (gsize) width / 2 && remain > 1; actual++, pos++, remain--)
 358             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 359 
 360         if (remain <= 1)
 361             goto finally;
 362         actual[0] = '~';
 363         actual++;
 364         remain--;
 365 
 366         pos += length - width + 1;
 367         for (; pos < length && remain > 1; pos++, actual++, remain--)
 368             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 369     }
 370     else
 371     {
 372         switch (HIDE_FIT (just_mode))
 373         {
 374         case J_CENTER:
 375             ident = (length - width) / 2;
 376             break;
 377         case J_RIGHT:
 378             ident = length - width;
 379             break;
 380         default:
 381             break;
 382         }
 383 
 384         pos += ident;
 385         for (; pos < (gsize) (ident + width) && remain > 1; pos++, actual++, remain--)
 386             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 387     }
 388 
 389   finally:
 390     if (actual >= result + sizeof (result))
 391         actual = result + sizeof (result) - 1;
 392     actual[0] = '\0';
 393     return result;
 394 }
 395 
 396 /* --------------------------------------------------------------------------------------------- */
 397 
 398 static const char *
 399 str_8bit_term_trim (const char *text, int width)
     /* [previous][next][first][last][top][bottom][index][help]  */
 400 {
 401     static char result[BUF_MEDIUM];
 402     size_t remain;
 403     char *actual;
 404     size_t length;
 405 
 406     length = strlen (text);
 407     actual = result;
 408     remain = sizeof (result);
 409 
 410     if (width > 0)
 411     {
 412         size_t pos;
 413 
 414         if (width >= (int) length)
 415         {
 416             for (pos = 0; pos < length && remain > 1; pos++, actual++, remain--)
 417                 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 418         }
 419         else if (width <= 3)
 420         {
 421             memset (actual, '.', width);
 422             actual += width;
 423         }
 424         else
 425         {
 426             memset (actual, '.', 3);
 427             actual += 3;
 428             remain -= 3;
 429 
 430             for (pos = length - width + 3; pos < length && remain > 1; pos++, actual++, remain--)
 431                 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 432         }
 433     }
 434 
 435     actual[0] = '\0';
 436     return result;
 437 }
 438 
 439 /* --------------------------------------------------------------------------------------------- */
 440 
 441 static int
 442 str_8bit_term_width2 (const char *text, size_t length)
     /* [previous][next][first][last][top][bottom][index][help]  */
 443 {
 444     return (length != (size_t) (-1)) ? MIN (strlen (text), length) : strlen (text);
 445 }
 446 
 447 /* --------------------------------------------------------------------------------------------- */
 448 
 449 static int
 450 str_8bit_term_width1 (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 451 {
 452     return str_8bit_term_width2 (text, (size_t) (-1));
 453 }
 454 
 455 /* --------------------------------------------------------------------------------------------- */
 456 
 457 static int
 458 str_8bit_term_char_width (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 459 {
 460     (void) text;
 461     return 1;
 462 }
 463 
 464 /* --------------------------------------------------------------------------------------------- */
 465 
 466 static const char *
 467 str_8bit_term_substring (const char *text, int start, int width)
     /* [previous][next][first][last][top][bottom][index][help]  */
 468 {
 469     static char result[BUF_MEDIUM];
 470     size_t remain;
 471     char *actual;
 472     size_t length;
 473 
 474     actual = result;
 475     remain = sizeof (result);
 476     length = strlen (text);
 477 
 478     if (start < (int) length)
 479     {
 480         size_t pos;
 481 
 482         for (pos = start; pos < length && width > 0 && remain > 1;
 483              pos++, width--, actual++, remain--)
 484             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 485     }
 486 
 487     for (; width > 0 && remain > 1; actual++, remain--, width--)
 488         actual[0] = ' ';
 489 
 490     actual[0] = '\0';
 491     return result;
 492 }
 493 
 494 /* --------------------------------------------------------------------------------------------- */
 495 
 496 static const char *
 497 str_8bit_trunc (const char *text, int width)
     /* [previous][next][first][last][top][bottom][index][help]  */
 498 {
 499     static char result[MC_MAXPATHLEN];
 500     int remain;
 501     char *actual;
 502     size_t pos = 0;
 503     size_t length;
 504 
 505     actual = result;
 506     remain = sizeof (result);
 507     length = strlen (text);
 508 
 509     if ((int) length > width)
 510     {
 511         for (; pos + 1 <= (gsize) width / 2 && remain > 1; actual++, pos++, remain--)
 512             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 513 
 514         if (remain <= 1)
 515             goto finally;
 516         actual[0] = '~';
 517         actual++;
 518         remain--;
 519 
 520         pos += length - width + 1;
 521         for (; pos < length && remain > 1; pos++, actual++, remain--)
 522             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 523     }
 524     else
 525     {
 526         for (; pos < length && remain > 1; pos++, actual++, remain--)
 527             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 528     }
 529 
 530   finally:
 531     actual[0] = '\0';
 532     return result;
 533 }
 534 
 535 /* --------------------------------------------------------------------------------------------- */
 536 
 537 static int
 538 str_8bit_offset_to_pos (const char *text, size_t length)
     /* [previous][next][first][last][top][bottom][index][help]  */
 539 {
 540     (void) text;
 541     return (int) length;
 542 }
 543 
 544 /* --------------------------------------------------------------------------------------------- */
 545 
 546 static int
 547 str_8bit_column_to_pos (const char *text, size_t pos)
     /* [previous][next][first][last][top][bottom][index][help]  */
 548 {
 549     (void) text;
 550     return (int) pos;
 551 }
 552 
 553 /* --------------------------------------------------------------------------------------------- */
 554 
 555 static char *
 556 str_8bit_create_search_needle (const char *needle, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 557 {
 558     (void) case_sen;
 559     return (char *) needle;
 560 }
 561 
 562 /* --------------------------------------------------------------------------------------------- */
 563 
 564 static void
 565 str_8bit_release_search_needle (char *needle, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 566 {
 567     (void) case_sen;
 568     (void) needle;
 569 }
 570 
 571 /* --------------------------------------------------------------------------------------------- */
 572 
 573 static char *
 574 str_8bit_strdown (const char *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 575 {
 576     char *rets, *p;
 577 
 578     if (str == NULL)
 579         return NULL;
 580 
 581     rets = g_strdup (str);
 582 
 583     for (p = rets; *p != '\0'; p++)
 584         *p = char_tolower (*p);
 585 
 586     return rets;
 587 }
 588 
 589 /* --------------------------------------------------------------------------------------------- */
 590 
 591 static const char *
 592 str_8bit_search_first (const char *text, const char *search, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 593 {
 594     char *fold_text;
 595     char *fold_search;
 596     const char *match;
 597 
 598     fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
 599     fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
 600 
 601     match = g_strstr_len (fold_text, -1, fold_search);
 602     if (match != NULL)
 603     {
 604         size_t offset;
 605 
 606         offset = match - fold_text;
 607         match = text + offset;
 608     }
 609 
 610     if (!case_sen)
 611     {
 612         g_free (fold_text);
 613         g_free (fold_search);
 614     }
 615 
 616     return match;
 617 }
 618 
 619 /* --------------------------------------------------------------------------------------------- */
 620 
 621 static const char *
 622 str_8bit_search_last (const char *text, const char *search, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 623 {
 624     char *fold_text;
 625     char *fold_search;
 626     const char *match;
 627 
 628     fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
 629     fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
 630 
 631     match = g_strrstr_len (fold_text, -1, fold_search);
 632     if (match != NULL)
 633     {
 634         size_t offset;
 635 
 636         offset = match - fold_text;
 637         match = text + offset;
 638     }
 639 
 640     if (!case_sen)
 641     {
 642         g_free (fold_text);
 643         g_free (fold_search);
 644     }
 645 
 646     return match;
 647 }
 648 
 649 /* --------------------------------------------------------------------------------------------- */
 650 
 651 static int
 652 str_8bit_compare (const char *t1, const char *t2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 653 {
 654     return strcmp (t1, t2);
 655 }
 656 
 657 /* --------------------------------------------------------------------------------------------- */
 658 
 659 static int
 660 str_8bit_ncompare (const char *t1, const char *t2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 661 {
 662     return strncmp (t1, t2, MIN (strlen (t1), strlen (t2)));
 663 }
 664 
 665 /* --------------------------------------------------------------------------------------------- */
 666 
 667 static int
 668 str_8bit_casecmp (const char *s1, const char *s2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 669 {
 670     /* code from GLib */
 671 
 672 #ifdef HAVE_STRCASECMP
 673     g_return_val_if_fail (s1 != NULL, 0);
 674     g_return_val_if_fail (s2 != NULL, 0);
 675 
 676     return strcasecmp (s1, s2);
 677 #else
 678     gint c1, c2;
 679 
 680     g_return_val_if_fail (s1 != NULL, 0);
 681     g_return_val_if_fail (s2 != NULL, 0);
 682 
 683     while (*s1 != '\0' && *s2 != '\0')
 684     {
 685         /* According to A. Cox, some platforms have islower's that
 686          * don't work right on non-uppercase
 687          */
 688         c1 = isupper ((guchar) * s1) ? tolower ((guchar) * s1) : *s1;
 689         c2 = isupper ((guchar) * s2) ? tolower ((guchar) * s2) : *s2;
 690         if (c1 != c2)
 691             return (c1 - c2);
 692         s1++;
 693         s2++;
 694     }
 695 
 696     return (((gint) (guchar) * s1) - ((gint) (guchar) * s2));
 697 #endif
 698 }
 699 
 700 /* --------------------------------------------------------------------------------------------- */
 701 
 702 static int
 703 str_8bit_ncasecmp (const char *s1, const char *s2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 704 {
 705     size_t n;
 706 
 707     g_return_val_if_fail (s1 != NULL, 0);
 708     g_return_val_if_fail (s2 != NULL, 0);
 709 
 710     n = MIN (strlen (s1), strlen (s2));
 711 
 712     /* code from GLib */
 713 
 714 #ifdef HAVE_STRNCASECMP
 715     return strncasecmp (s1, s2, n);
 716 #else
 717     gint c1, c2;
 718 
 719     while (n != 0 && *s1 != '\0' && *s2 != '\0')
 720     {
 721         n -= 1;
 722         /* According to A. Cox, some platforms have islower's that
 723          * don't work right on non-uppercase
 724          */
 725         c1 = isupper ((guchar) * s1) ? tolower ((guchar) * s1) : *s1;
 726         c2 = isupper ((guchar) * s2) ? tolower ((guchar) * s2) : *s2;
 727         if (c1 != c2)
 728             return (c1 - c2);
 729         s1++;
 730         s2++;
 731     }
 732 
 733     if (n == 0)
 734         return 0;
 735 
 736     return (((gint) (guchar) * s1) - ((gint) (guchar) * s2));
 737 
 738 #endif
 739 }
 740 
 741 /* --------------------------------------------------------------------------------------------- */
 742 
 743 static int
 744 str_8bit_prefix (const char *text, const char *prefix)
     /* [previous][next][first][last][top][bottom][index][help]  */
 745 {
 746     int result;
 747 
 748     for (result = 0; text[result] != '\0' && prefix[result] != '\0'
 749          && text[result] == prefix[result]; result++);
 750 
 751     return result;
 752 }
 753 
 754 /* --------------------------------------------------------------------------------------------- */
 755 
 756 static int
 757 str_8bit_caseprefix (const char *text, const char *prefix)
     /* [previous][next][first][last][top][bottom][index][help]  */
 758 {
 759     int result;
 760 
 761     for (result = 0; text[result] != '\0' && prefix[result] != '\0'
 762          && char_toupper (text[result]) == char_toupper (prefix[result]); result++);
 763 
 764     return result;
 765 }
 766 
 767 /* --------------------------------------------------------------------------------------------- */
 768 
 769 static void
 770 str_8bit_fix_string (char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 771 {
 772     (void) text;
 773 }
 774 
 775 /* --------------------------------------------------------------------------------------------- */
 776 
 777 static char *
 778 str_8bit_create_key (const char *text, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 779 {
 780     return case_sen ? (char *) text : str_8bit_strdown (text);
 781 }
 782 
 783 /* --------------------------------------------------------------------------------------------- */
 784 
 785 static int
 786 str_8bit_key_collate (const char *t1, const char *t2, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 787 {
 788     return case_sen ? strcmp (t1, t2) : strcoll (t1, t2);
 789 }
 790 
 791 /* --------------------------------------------------------------------------------------------- */
 792 
 793 static void
 794 str_8bit_release_key (char *key, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 795 {
 796     if (!case_sen)
 797         g_free (key);
 798 }
 799 
 800 /* --------------------------------------------------------------------------------------------- */
 801 /*** public functions ****************************************************************************/
 802 /* --------------------------------------------------------------------------------------------- */
 803 
 804 struct str_class
 805 str_8bit_init (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 806 {
 807     struct str_class result;
 808 
 809     result.conv_gerror_message = str_8bit_conv_gerror_message;
 810     result.vfs_convert_to = str_8bit_vfs_convert_to;
 811     result.insert_replace_char = str_8bit_insert_replace_char;
 812     result.is_valid_string = str_8bit_is_valid_string;
 813     result.is_valid_char = str_8bit_is_valid_char;
 814     result.cnext_char = str_8bit_cnext_char;
 815     result.cprev_char = str_8bit_cprev_char;
 816     result.cnext_char_safe = str_8bit_cnext_char;
 817     result.cprev_char_safe = str_8bit_cprev_char;
 818     result.cnext_noncomb_char = str_8bit_cnext_noncomb_char;
 819     result.cprev_noncomb_char = str_8bit_cprev_noncomb_char;
 820     result.char_isspace = str_8bit_isspace;
 821     result.char_ispunct = str_8bit_ispunct;
 822     result.char_isalnum = str_8bit_isalnum;
 823     result.char_isdigit = str_8bit_isdigit;
 824     result.char_isprint = str_8bit_isprint;
 825     result.char_iscombiningmark = str_8bit_iscombiningmark;
 826     result.char_toupper = str_8bit_toupper;
 827     result.char_tolower = str_8bit_tolower;
 828     result.length = str_8bit_length;
 829     result.length2 = str_8bit_length2;
 830     result.length_noncomb = str_8bit_length;
 831     result.fix_string = str_8bit_fix_string;
 832     result.term_form = str_8bit_term_form;
 833     result.fit_to_term = str_8bit_fit_to_term;
 834     result.term_trim = str_8bit_term_trim;
 835     result.term_width2 = str_8bit_term_width2;
 836     result.term_width1 = str_8bit_term_width1;
 837     result.term_char_width = str_8bit_term_char_width;
 838     result.term_substring = str_8bit_term_substring;
 839     result.trunc = str_8bit_trunc;
 840     result.offset_to_pos = str_8bit_offset_to_pos;
 841     result.column_to_pos = str_8bit_column_to_pos;
 842     result.create_search_needle = str_8bit_create_search_needle;
 843     result.release_search_needle = str_8bit_release_search_needle;
 844     result.search_first = str_8bit_search_first;
 845     result.search_last = str_8bit_search_last;
 846     result.compare = str_8bit_compare;
 847     result.ncompare = str_8bit_ncompare;
 848     result.casecmp = str_8bit_casecmp;
 849     result.ncasecmp = str_8bit_ncasecmp;
 850     result.prefix = str_8bit_prefix;
 851     result.caseprefix = str_8bit_caseprefix;
 852     result.create_key = str_8bit_create_key;
 853     result.create_key_for_filename = str_8bit_create_key;
 854     result.key_collate = str_8bit_key_collate;
 855     result.release_key = str_8bit_release_key;
 856 
 857     return result;
 858 }
 859 
 860 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */