bidi.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (C) 2003 Mooffie <mooffie@typo.co.il>
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  16. #include <config.h>
  17. #include "bidi.h"
  18. #include "dbg.h"
  19. static ctype_t fribidi_dir(direction_t dir)
  20. {
  21. switch (dir) {
  22. case dirLTR: return FRIBIDI_TYPE_LTR;
  23. case dirRTL: return FRIBIDI_TYPE_RTL;
  24. default: return FRIBIDI_TYPE_ON;
  25. }
  26. }
  27. void BiDi::get_embedding_levels(unichar *str, idx_t len,
  28. direction_t dir,
  29. level_t *levels,
  30. int line_breaks_count,
  31. idx_t *line_breaks,
  32. bool disable_bidi)
  33. {
  34. if (disable_bidi) {
  35. for (idx_t i = len-1; i >= 0; i--)
  36. levels[i] = (dir == dirRTL) ? 1 :0;
  37. } else {
  38. ctype_t base_dir = fribidi_dir(dir);
  39. fribidi_log2vis_get_embedding_levels(str, len, &base_dir, levels);
  40. }
  41. // Do rule L1.4 of TR9: wspaces at end of lines.
  42. level_t para_embedding_level = (dir == dirRTL ? 1 : 0);
  43. int prev_line_break = 0;
  44. for (int i = 0; i < line_breaks_count; i++) {
  45. int pos = (int)line_breaks[i] - 1;
  46. while (pos >= prev_line_break && is_space(str[pos])) {
  47. levels[pos] = para_embedding_level;
  48. pos--;
  49. }
  50. prev_line_break = line_breaks[i];
  51. }
  52. }
  53. static void xsimple_log2vis(unichar *str, idx_t len, direction_t dir,
  54. unichar *dest)
  55. {
  56. ctype_t base_dir = fribidi_dir(dir);
  57. fribidi_log2vis(str, len, &base_dir, dest, NULL, NULL, NULL);
  58. }
  59. void BiDi::simple_log2vis(unistring &str, direction_t dir, unistring &dest)
  60. {
  61. dest.resize(str.size() + 1); // fribidi_log2vis needs "+1" !!!!!!!!!!!!!
  62. xsimple_log2vis(str.begin(), str.size(), dir, dest.begin());
  63. dest.resize(str.size());
  64. }
  65. // determine_base_dir() - determines the base direction of a string.
  66. // We provide the user with several algorithms. algoUnicode is described
  67. // in P2,3 of TR9.
  68. //
  69. // algoContext's implementation is divided into two: half is here and
  70. // the other half is in EditBox::calc_contextual_dirs(). See documentation
  71. // there.
  72. direction_t BiDi::determine_base_dir(unichar *str, idx_t len,
  73. diralgo_t dir_algo)
  74. {
  75. ctype_t ctype;
  76. switch (dir_algo) {
  77. case algoContextRTL:
  78. {
  79. // - if there's any RTL letter, set direction to LTR;
  80. // - else: if there's any LTR letter, set direction to LTR;
  81. // - else: set direction to neutral.
  82. bool found_LTR = false;
  83. for (idx_t i = 0; i < len; i++) {
  84. ctype = fribidi_get_type(str[i]);
  85. if (FRIBIDI_IS_LETTER(ctype)) {
  86. if (FRIBIDI_IS_RTL(ctype))
  87. return dirRTL;
  88. else
  89. found_LTR = true;
  90. }
  91. }
  92. if (found_LTR)
  93. return dirLTR;
  94. else
  95. return dirN;
  96. }
  97. case algoUnicode:
  98. case algoContextStrong:
  99. {
  100. // directionality is determined by the first strong letter.
  101. for (idx_t i = 0; i < len; i++) {
  102. ctype = fribidi_get_type(str[i]);
  103. if (FRIBIDI_IS_LETTER(ctype)) {
  104. if (FRIBIDI_IS_RTL(ctype))
  105. return dirRTL;
  106. else
  107. return dirLTR;
  108. }
  109. }
  110. if (dir_algo == algoContextStrong)
  111. return dirN;
  112. else
  113. return dirLTR;
  114. }
  115. case algoForceRTL:
  116. return dirRTL;
  117. case algoForceLTR:
  118. default:
  119. return dirLTR;
  120. };
  121. }