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-2024
   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 /*** forward declarations (file scope functions) *************************************************/
  60 
  61 /*** file scope variables ************************************************************************/
  62 
  63 static const char replch = '?';
  64 
  65 /* --------------------------------------------------------------------------------------------- */
  66 /*** file scope functions ************************************************************************/
  67 /* --------------------------------------------------------------------------------------------- */
  68 
  69 /* *INDENT-OFF* */
  70 DECLARE_CTYPE_WRAPPER (isalnum)
     /* [previous][next][first][last][top][bottom][index][help]  */
  71 DECLARE_CTYPE_WRAPPER (isdigit)
  72 DECLARE_CTYPE_WRAPPER (isprint)
  73 DECLARE_CTYPE_WRAPPER (ispunct)
  74 DECLARE_CTYPE_WRAPPER (isspace)
  75 DECLARE_CTYPE_WRAPPER (toupper)
  76 DECLARE_CTYPE_WRAPPER (tolower)
  77 /* *INDENT-ON* */
  78 
  79 /* --------------------------------------------------------------------------------------------- */
  80 
  81 static void
  82 str_8bit_insert_replace_char (GString * buffer)
  83 {
  84     g_string_append_c (buffer, replch);
  85 }
  86 
  87 /* --------------------------------------------------------------------------------------------- */
  88 
  89 static gboolean
  90 str_8bit_is_valid_string (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
  91 {
  92     (void) text;
  93     return TRUE;
  94 }
  95 
  96 /* --------------------------------------------------------------------------------------------- */
  97 
  98 static int
  99 str_8bit_is_valid_char (const char *ch, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 100 {
 101     (void) ch;
 102     (void) size;
 103     return 1;
 104 }
 105 
 106 /* --------------------------------------------------------------------------------------------- */
 107 
 108 static void
 109 str_8bit_cnext_char (const char **text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 110 {
 111     (*text)++;
 112 }
 113 
 114 /* --------------------------------------------------------------------------------------------- */
 115 
 116 static void
 117 str_8bit_cprev_char (const char **text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 118 {
 119     (*text)--;
 120 }
 121 
 122 /* --------------------------------------------------------------------------------------------- */
 123 
 124 static int
 125 str_8bit_cnext_noncomb_char (const char **text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 126 {
 127     if (*text[0] == '\0')
 128         return 0;
 129 
 130     (*text)++;
 131     return 1;
 132 }
 133 
 134 /* --------------------------------------------------------------------------------------------- */
 135 
 136 static int
 137 str_8bit_cprev_noncomb_char (const char **text, const char *begin)
     /* [previous][next][first][last][top][bottom][index][help]  */
 138 {
 139     if ((*text) == begin)
 140         return 0;
 141 
 142     (*text)--;
 143     return 1;
 144 }
 145 
 146 /* --------------------------------------------------------------------------------------------- */
 147 
 148 static gboolean
 149 str_8bit_isspace (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 150 {
 151     return char_isspace (text[0]) != 0;
 152 }
 153 
 154 /* --------------------------------------------------------------------------------------------- */
 155 
 156 static gboolean
 157 str_8bit_ispunct (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 158 {
 159     return char_ispunct (text[0]) != 0;
 160 }
 161 
 162 /* --------------------------------------------------------------------------------------------- */
 163 
 164 static gboolean
 165 str_8bit_isalnum (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 166 {
 167     return char_isalnum (text[0]) != 0;
 168 }
 169 
 170 /* --------------------------------------------------------------------------------------------- */
 171 
 172 static gboolean
 173 str_8bit_isdigit (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 174 {
 175     return char_isdigit (text[0]) != 0;
 176 }
 177 
 178 /* --------------------------------------------------------------------------------------------- */
 179 
 180 static gboolean
 181 str_8bit_isprint (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 182 {
 183     return char_isprint (text[0]) != 0;
 184 }
 185 
 186 /* --------------------------------------------------------------------------------------------- */
 187 
 188 static gboolean
 189 str_8bit_iscombiningmark (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 190 {
 191     (void) text;
 192     return FALSE;
 193 }
 194 
 195 /* --------------------------------------------------------------------------------------------- */
 196 
 197 static int
 198 str_8bit_toupper (const char *text, char **out, size_t * remain)
     /* [previous][next][first][last][top][bottom][index][help]  */
 199 {
 200     if (*remain <= 1)
 201         return FALSE;
 202 
 203     (*out)[0] = char_toupper (text[0]);
 204     (*out)++;
 205     (*remain)--;
 206     return TRUE;
 207 }
 208 
 209 /* --------------------------------------------------------------------------------------------- */
 210 
 211 static gboolean
 212 str_8bit_tolower (const char *text, char **out, size_t * remain)
     /* [previous][next][first][last][top][bottom][index][help]  */
 213 {
 214     if (*remain <= 1)
 215         return FALSE;
 216 
 217     (*out)[0] = char_tolower (text[0]);
 218     (*out)++;
 219     (*remain)--;
 220     return TRUE;
 221 }
 222 
 223 /* --------------------------------------------------------------------------------------------- */
 224 
 225 static int
 226 str_8bit_length (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 227 {
 228     return strlen (text);
 229 }
 230 
 231 /* --------------------------------------------------------------------------------------------- */
 232 
 233 static int
 234 str_8bit_length2 (const char *text, int size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 235 {
 236     return (size >= 0) ? MIN (strlen (text), (gsize) size) : strlen (text);
 237 }
 238 
 239 /* --------------------------------------------------------------------------------------------- */
 240 
 241 static gchar *
 242 str_8bit_conv_gerror_message (GError * mcerror, const char *def_msg)
     /* [previous][next][first][last][top][bottom][index][help]  */
 243 {
 244     GIConv conv;
 245     gchar *ret;
 246 
 247     /* glib messages are in UTF-8 charset */
 248     conv = str_crt_conv_from ("UTF-8");
 249 
 250     if (conv == INVALID_CONV)
 251         ret = g_strdup (def_msg != NULL ? def_msg : "");
 252     else
 253     {
 254         GString *buf;
 255 
 256         buf = g_string_new ("");
 257 
 258         if (str_convert (conv, mcerror->message, buf) != ESTR_FAILURE)
 259             ret = g_string_free (buf, FALSE);
 260         else
 261         {
 262             ret = g_strdup (def_msg != NULL ? def_msg : "");
 263             g_string_free (buf, TRUE);
 264         }
 265 
 266         str_close_conv (conv);
 267     }
 268 
 269     return ret;
 270 }
 271 
 272 /* --------------------------------------------------------------------------------------------- */
 273 
 274 static estr_t
 275 str_8bit_vfs_convert_to (GIConv coder, const char *string, int size, GString * buffer)
     /* [previous][next][first][last][top][bottom][index][help]  */
 276 {
 277     estr_t result = ESTR_SUCCESS;
 278 
 279     if (coder == str_cnv_not_convert)
 280         g_string_append_len (buffer, string, size);
 281     else
 282         result = str_nconvert (coder, string, size, buffer);
 283 
 284     return result;
 285 }
 286 
 287 /* --------------------------------------------------------------------------------------------- */
 288 
 289 static const char *
 290 str_8bit_term_form (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 291 {
 292     static char result[BUF_MEDIUM];
 293     char *actual;
 294     size_t remain;
 295     size_t length;
 296     size_t pos = 0;
 297 
 298     actual = result;
 299     remain = sizeof (result);
 300     length = strlen (text);
 301 
 302     for (; pos < length && remain > 1; pos++, actual++, remain--)
 303         actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 304 
 305     actual[0] = '\0';
 306     return result;
 307 }
 308 
 309 /* --------------------------------------------------------------------------------------------- */
 310 
 311 static const char *
 312 str_8bit_fit_to_term (const char *text, int width, align_crt_t just_mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
 313 {
 314     static char result[BUF_MEDIUM];
 315     char *actual;
 316     size_t remain;
 317     int ident = 0;
 318     size_t length;
 319     size_t pos = 0;
 320 
 321     length = strlen (text);
 322     actual = result;
 323     remain = sizeof (result);
 324 
 325     if ((int) length <= width)
 326     {
 327         switch (HIDE_FIT (just_mode))
 328         {
 329         case J_CENTER_LEFT:
 330         case J_CENTER:
 331             ident = (width - length) / 2;
 332             break;
 333         case J_RIGHT:
 334             ident = width - length;
 335             break;
 336         default:
 337             break;
 338         }
 339 
 340         if ((int) remain <= ident)
 341             goto finally;
 342         memset (actual, ' ', ident);
 343         actual += ident;
 344         remain -= ident;
 345 
 346         for (; pos < length && remain > 1; pos++, actual++, remain--)
 347             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 348 
 349         if (width - length - ident > 0)
 350         {
 351             if (remain <= width - length - ident)
 352                 goto finally;
 353             memset (actual, ' ', width - length - ident);
 354             actual += width - length - ident;
 355         }
 356     }
 357     else if (IS_FIT (just_mode))
 358     {
 359         for (; pos + 1 <= (gsize) width / 2 && remain > 1; actual++, pos++, remain--)
 360             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 361 
 362         if (remain <= 1)
 363             goto finally;
 364         actual[0] = '~';
 365         actual++;
 366         remain--;
 367 
 368         pos += length - width + 1;
 369         for (; pos < length && remain > 1; pos++, actual++, remain--)
 370             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 371     }
 372     else
 373     {
 374         switch (HIDE_FIT (just_mode))
 375         {
 376         case J_CENTER:
 377             ident = (length - width) / 2;
 378             break;
 379         case J_RIGHT:
 380             ident = length - width;
 381             break;
 382         default:
 383             break;
 384         }
 385 
 386         pos += ident;
 387         for (; pos < (gsize) (ident + width) && remain > 1; pos++, actual++, remain--)
 388             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 389     }
 390 
 391   finally:
 392     if (actual >= result + sizeof (result))
 393         actual = result + sizeof (result) - 1;
 394     actual[0] = '\0';
 395     return result;
 396 }
 397 
 398 /* --------------------------------------------------------------------------------------------- */
 399 
 400 static const char *
 401 str_8bit_term_trim (const char *text, int width)
     /* [previous][next][first][last][top][bottom][index][help]  */
 402 {
 403     static char result[BUF_MEDIUM];
 404     size_t remain;
 405     char *actual;
 406     size_t length;
 407 
 408     length = strlen (text);
 409     actual = result;
 410     remain = sizeof (result);
 411 
 412     if (width > 0)
 413     {
 414         size_t pos;
 415 
 416         if (width >= (int) length)
 417         {
 418             for (pos = 0; pos < length && remain > 1; pos++, actual++, remain--)
 419                 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 420         }
 421         else if (width <= 3)
 422         {
 423             memset (actual, '.', width);
 424             actual += width;
 425         }
 426         else
 427         {
 428             memset (actual, '.', 3);
 429             actual += 3;
 430             remain -= 3;
 431 
 432             for (pos = length - width + 3; pos < length && remain > 1; pos++, actual++, remain--)
 433                 actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 434         }
 435     }
 436 
 437     actual[0] = '\0';
 438     return result;
 439 }
 440 
 441 /* --------------------------------------------------------------------------------------------- */
 442 
 443 static int
 444 str_8bit_term_width2 (const char *text, size_t length)
     /* [previous][next][first][last][top][bottom][index][help]  */
 445 {
 446     return (length != (size_t) (-1)) ? MIN (strlen (text), length) : strlen (text);
 447 }
 448 
 449 /* --------------------------------------------------------------------------------------------- */
 450 
 451 static int
 452 str_8bit_term_width1 (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 453 {
 454     return str_8bit_term_width2 (text, (size_t) (-1));
 455 }
 456 
 457 /* --------------------------------------------------------------------------------------------- */
 458 
 459 static int
 460 str_8bit_term_char_width (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 461 {
 462     (void) text;
 463     return 1;
 464 }
 465 
 466 /* --------------------------------------------------------------------------------------------- */
 467 
 468 static const char *
 469 str_8bit_term_substring (const char *text, int start, int width)
     /* [previous][next][first][last][top][bottom][index][help]  */
 470 {
 471     static char result[BUF_MEDIUM];
 472     size_t remain;
 473     char *actual;
 474     size_t length;
 475 
 476     actual = result;
 477     remain = sizeof (result);
 478     length = strlen (text);
 479 
 480     if (start < (int) length)
 481     {
 482         size_t pos;
 483 
 484         for (pos = start; pos < length && width > 0 && remain > 1;
 485              pos++, width--, actual++, remain--)
 486             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 487     }
 488 
 489     for (; width > 0 && remain > 1; actual++, remain--, width--)
 490         actual[0] = ' ';
 491 
 492     actual[0] = '\0';
 493     return result;
 494 }
 495 
 496 /* --------------------------------------------------------------------------------------------- */
 497 
 498 static const char *
 499 str_8bit_trunc (const char *text, int width)
     /* [previous][next][first][last][top][bottom][index][help]  */
 500 {
 501     static char result[MC_MAXPATHLEN];
 502     int remain;
 503     char *actual;
 504     size_t pos = 0;
 505     size_t length;
 506 
 507     actual = result;
 508     remain = sizeof (result);
 509     length = strlen (text);
 510 
 511     if ((int) length > width)
 512     {
 513         for (; pos + 1 <= (gsize) width / 2 && remain > 1; actual++, pos++, remain--)
 514             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 515 
 516         if (remain <= 1)
 517             goto finally;
 518         actual[0] = '~';
 519         actual++;
 520         remain--;
 521 
 522         pos += length - width + 1;
 523         for (; pos < length && remain > 1; pos++, actual++, remain--)
 524             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 525     }
 526     else
 527     {
 528         for (; pos < length && remain > 1; pos++, actual++, remain--)
 529             actual[0] = char_isprint (text[pos]) ? text[pos] : '.';
 530     }
 531 
 532   finally:
 533     actual[0] = '\0';
 534     return result;
 535 }
 536 
 537 /* --------------------------------------------------------------------------------------------- */
 538 
 539 static int
 540 str_8bit_offset_to_pos (const char *text, size_t length)
     /* [previous][next][first][last][top][bottom][index][help]  */
 541 {
 542     (void) text;
 543     return (int) length;
 544 }
 545 
 546 /* --------------------------------------------------------------------------------------------- */
 547 
 548 static int
 549 str_8bit_column_to_pos (const char *text, size_t pos)
     /* [previous][next][first][last][top][bottom][index][help]  */
 550 {
 551     (void) text;
 552     return (int) pos;
 553 }
 554 
 555 /* --------------------------------------------------------------------------------------------- */
 556 
 557 static char *
 558 str_8bit_create_search_needle (const char *needle, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 559 {
 560     (void) case_sen;
 561     return (char *) needle;
 562 }
 563 
 564 /* --------------------------------------------------------------------------------------------- */
 565 
 566 static void
 567 str_8bit_release_search_needle (char *needle, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 568 {
 569     (void) case_sen;
 570     (void) needle;
 571 }
 572 
 573 /* --------------------------------------------------------------------------------------------- */
 574 
 575 static char *
 576 str_8bit_strdown (const char *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 577 {
 578     char *rets, *p;
 579 
 580     if (str == NULL)
 581         return NULL;
 582 
 583     rets = g_strdup (str);
 584 
 585     for (p = rets; *p != '\0'; p++)
 586         *p = char_tolower (*p);
 587 
 588     return rets;
 589 }
 590 
 591 /* --------------------------------------------------------------------------------------------- */
 592 
 593 static const char *
 594 str_8bit_search_first (const char *text, const char *search, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 595 {
 596     char *fold_text;
 597     char *fold_search;
 598     const char *match;
 599 
 600     fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
 601     fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
 602 
 603     match = g_strstr_len (fold_text, -1, fold_search);
 604     if (match != NULL)
 605     {
 606         size_t offset;
 607 
 608         offset = match - fold_text;
 609         match = text + offset;
 610     }
 611 
 612     if (!case_sen)
 613     {
 614         g_free (fold_text);
 615         g_free (fold_search);
 616     }
 617 
 618     return match;
 619 }
 620 
 621 /* --------------------------------------------------------------------------------------------- */
 622 
 623 static const char *
 624 str_8bit_search_last (const char *text, const char *search, gboolean case_sen)
     /* [previous][next][first][last][top][bottom][index][help]  */
 625 {
 626     char *fold_text;
 627     char *fold_search;
 628     const char *match;
 629 
 630     fold_text = case_sen ? (char *) text : str_8bit_strdown (text);
 631     fold_search = case_sen ? (char *) search : str_8bit_strdown (search);
 632 
 633     match = g_strrstr_len (fold_text, -1, fold_search);
 634     if (match != NULL)
 635     {
 636         size_t offset;
 637 
 638         offset = match - fold_text;
 639         match = text + offset;
 640     }
 641 
 642     if (!case_sen)
 643     {
 644         g_free (fold_text);
 645         g_free (fold_search);
 646     }
 647 
 648     return match;
 649 }
 650 
 651 /* --------------------------------------------------------------------------------------------- */
 652 
 653 static int
 654 str_8bit_compare (const char *t1, const char *t2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 655 {
 656     return strcmp (t1, t2);
 657 }
 658 
 659 /* --------------------------------------------------------------------------------------------- */
 660 
 661 static int
 662 str_8bit_ncompare (const char *t1, const char *t2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 663 {
 664     return strncmp (t1, t2, MIN (strlen (t1), strlen (t2)));
 665 }
 666 
 667 /* --------------------------------------------------------------------------------------------- */
 668 
 669 static int
 670 str_8bit_casecmp (const char *s1, const char *s2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 671 {
 672     /* code from GLib */
 673 
 674 #ifdef HAVE_STRCASECMP
 675     g_return_val_if_fail (s1 != NULL, 0);
 676     g_return_val_if_fail (s2 != NULL, 0);
 677 
 678     return strcasecmp (s1, s2);
 679 #else
 680 
 681     g_return_val_if_fail (s1 != NULL, 0);
 682     g_return_val_if_fail (s2 != NULL, 0);
 683 
 684     for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++)
 685     {
 686         gint c1, c2;
 687 
 688         /* According to A. Cox, some platforms have islower's that
 689          * don't work right on non-uppercase
 690          */
 691         c1 = isupper ((guchar) * s1) ? tolower ((guchar) * s1) : *s1;
 692         c2 = isupper ((guchar) * s2) ? tolower ((guchar) * s2) : *s2;
 693         if (c1 != c2)
 694             return (c1 - c2);
 695     }
 696 
 697     return (((gint) (guchar) * s1) - ((gint) (guchar) * s2));
 698 #endif
 699 }
 700 
 701 /* --------------------------------------------------------------------------------------------- */
 702 
 703 static int
 704 str_8bit_ncasecmp (const char *s1, const char *s2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 705 {
 706     size_t n;
 707 
 708     g_return_val_if_fail (s1 != NULL, 0);
 709     g_return_val_if_fail (s2 != NULL, 0);
 710 
 711     n = MIN (strlen (s1), strlen (s2));
 712 
 713     /* code from GLib */
 714 
 715 #ifdef HAVE_STRNCASECMP
 716     return strncasecmp (s1, s2, n);
 717 #else
 718 
 719     for (; *s1 != '\0' && *s2 != '\0'; s1++, s2++)
 720     {
 721         gint c1, c2;
 722 
 723         n--;
 724         /* According to A. Cox, some platforms have islower's that
 725          * don't work right on non-uppercase
 726          */
 727         c1 = isupper ((guchar) * s1) ? tolower ((guchar) * s1) : *s1;
 728         c2 = isupper ((guchar) * s2) ? tolower ((guchar) * s2) : *s2;
 729         if (c1 != c2)
 730             return (c1 - c2);
 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]  */