+#define GET_LB_TYPE(MT, POS, LB_TYPE) \
+ do { \
+ int c = mtext_ref_char ((MT), (POS)); \
+ (LB_TYPE) = ((c == ' ' || c == '\t' || c == '\n') ? M_kinsoku_bol \
+ : mchartable_lookup (linebreak_table, c)); \
+ } while (0)
+
+static int
+find_break_backward (MText *mt, int pos, int limit)
+{
+ MSymbol lb_type;
+
+ if (pos <= limit)
+ return limit;
+
+ GET_LB_TYPE (mt, pos, lb_type);
+ if (lb_type == M_kinsoku_bol)
+ return find_break_backward (mt, pos - 1, limit);
+ if (lb_type == Mnil)
+ {
+ while (pos > limit)
+ {
+ GET_LB_TYPE (mt, pos - 1, lb_type);
+ if (lb_type != Mnil)
+ break;
+ pos--;
+ }
+ }
+ else if (lb_type == M_break_at_word)
+ {
+ int beg = limit, end = mtext_nchars (mt);
+ int in_word = mtext__word_segment (mt, pos, &beg, &end);
+
+ if (in_word)
+ pos = beg;
+ else if (beg > limit)
+ {
+ end = beg;
+ beg = limit;
+ mtext__word_segment (mt, beg - 1, &beg, &end);
+ pos = beg;
+ }
+ }
+ while (pos > limit)
+ {
+ GET_LB_TYPE (mt, pos - 1, lb_type);
+ if (lb_type != M_kinsoku_eol)
+ return pos;
+ pos--;
+ }
+ return limit;
+}
+
+static int
+find_break_forward (MText *mt, int pos, int limit)
+{
+ MSymbol lb_type;
+
+ GET_LB_TYPE (mt, pos, lb_type);
+ if (lb_type == Mnil)
+ {
+ while (pos < limit)
+ {
+ pos++;
+ GET_LB_TYPE (mt, pos, lb_type);
+ }
+ }
+ else if (lb_type == M_break_at_word)
+ {
+ int beg = 0, end = mtext_nchars (mt);
+ int in_word = mtext__word_segment (mt, pos, &beg, &end);
+
+ if (! in_word)
+ pos = end;
+ else if (end < limit)
+ {
+ beg = end;
+ pos = end = mtext_nchars (mt);
+ mtext__word_segment (mt, pos, &beg, &end);
+ pos = end;
+ }
+ }
+ else if (lb_type == M_kinsoku_bol)
+ pos++;
+ while (pos < limit)
+ {
+ GET_LB_TYPE (mt, pos, lb_type);
+ if (lb_type != M_kinsoku_bol)
+ return pos;
+ pos++;
+ }
+ return limit;
+}
+