string.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright (C) 2004-2020 Igor van den Hoven *
  5. * *
  6. * TinTin++ is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 3 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  18. ******************************************************************************/
  19. /******************************************************************************
  20. * T I N T I N + + *
  21. * *
  22. * coded by Igor van den Hoven 2020 *
  23. ******************************************************************************/
  24. #include "tintin.h"
  25. int str_len_str(struct session *ses, char *str, int start, int end)
  26. {
  27. int raw_cnt, str_cnt, ret_cnt, width, raw_len, tmp_cnt;
  28. raw_cnt = 0;
  29. str_cnt = 0;
  30. ret_cnt = 0;
  31. raw_len = str_len(str);
  32. while (raw_cnt < raw_len)
  33. {
  34. if (end >= 0 && str_cnt >= end)
  35. {
  36. break;
  37. }
  38. tmp_cnt = skip_vt102_codes(&str[raw_cnt]);
  39. if (tmp_cnt)
  40. {
  41. raw_cnt += tmp_cnt;
  42. }
  43. else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
  44. {
  45. raw_cnt += get_utf8_width(&str[raw_cnt], &width);
  46. if (str_cnt >= start)
  47. {
  48. ret_cnt += width;
  49. }
  50. str_cnt += width;
  51. }
  52. else
  53. {
  54. if (str_cnt >= start)
  55. {
  56. ret_cnt++;
  57. }
  58. raw_cnt++;
  59. str_cnt++;
  60. }
  61. }
  62. return ret_cnt;
  63. }
  64. int str_len_raw(struct session *ses, char *str, int start, int end)
  65. {
  66. int raw_cnt, ret_cnt, width, raw_len, tmp_cnt;
  67. raw_cnt = start;
  68. ret_cnt = 0;
  69. raw_len = str_len(str);
  70. while (raw_cnt < raw_len)
  71. {
  72. if (raw_cnt >= end)
  73. {
  74. break;
  75. }
  76. tmp_cnt = skip_vt102_codes(&str[raw_cnt]);
  77. if (tmp_cnt)
  78. {
  79. // can go past end, but shouldn't be an issue
  80. raw_cnt += tmp_cnt;
  81. }
  82. else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
  83. {
  84. raw_cnt += get_utf8_width(&str[raw_cnt], &width);
  85. ret_cnt += width;
  86. }
  87. else
  88. {
  89. raw_cnt++;
  90. ret_cnt++;
  91. }
  92. }
  93. return ret_cnt;
  94. }
  95. int raw_len_str(struct session *ses, char *str, int start, int end)
  96. {
  97. int raw_cnt, str_cnt, ret_cnt, width, tmp_cnt, raw_len;
  98. raw_cnt = 0;
  99. str_cnt = 0;
  100. ret_cnt = 0;
  101. raw_len = strlen(str);
  102. while (raw_cnt < raw_len)
  103. {
  104. tmp_cnt = skip_vt102_codes(&str[raw_cnt]);
  105. if (tmp_cnt)
  106. {
  107. raw_cnt += tmp_cnt;
  108. if (str_cnt >= start)
  109. {
  110. ret_cnt += tmp_cnt;
  111. }
  112. width = 0;
  113. }
  114. else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
  115. {
  116. tmp_cnt = get_utf8_width(&str[raw_cnt], &width);
  117. if (str_cnt >= start)
  118. {
  119. ret_cnt += tmp_cnt;
  120. }
  121. raw_cnt += tmp_cnt;
  122. }
  123. else
  124. {
  125. if (str_cnt >= start)
  126. {
  127. ret_cnt++;
  128. }
  129. raw_cnt++;
  130. width = 1;
  131. }
  132. if (end >= 0 && str_cnt + width > end)
  133. {
  134. break;
  135. }
  136. str_cnt += width;
  137. }
  138. return ret_cnt;
  139. }
  140. int raw_len_raw(struct session *ses, char *str, int start, int end)
  141. {
  142. if (start >= end)
  143. {
  144. return 0;
  145. }
  146. return end - start;
  147. }
  148. char *str_ins_str(struct session *ses, char **str, char *ins, int str_start, int str_end)
  149. {
  150. int len, raw_start, raw_end, raw_len, ins_raw_len;
  151. len = str_len_str(ses, *str, 0, str_end);
  152. if (len < str_end)
  153. {
  154. str_cat_printf(str, "%*s", str_end - len, "");
  155. }
  156. ins_raw_len = raw_len_str(ses, ins, 0, str_end - str_start);
  157. raw_start = raw_len_str(ses, *str, 0, str_start);
  158. raw_len = raw_len_str(ses, *str, 0, -1);
  159. raw_end = raw_len_str(ses, *str, 0, str_end);
  160. if (raw_len < raw_end + ins_raw_len)
  161. {
  162. str_resize(str, ins_raw_len);
  163. memmove(*str + raw_start + ins_raw_len, *str + raw_end, raw_len - raw_end + 1);
  164. memcpy(*str + raw_start, ins, ins_raw_len);
  165. }
  166. else
  167. {
  168. memcpy(*str + raw_start, ins, ins_raw_len);
  169. (*str)[raw_start + ins_raw_len] = 0;
  170. }
  171. str_fix(*str);
  172. return *str;
  173. }