ref: d173cf1cdc72519809a0e3e01165f616044b2eee
parent: d81da34389f192fee51865798fc86ff7e521617a
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Jun 11 12:53:36 EDT 2013
fmt: keshideh justification With ".ad k", neatroff inserts keshideh characters inside words of filled lines, before adjusting with spaces.
--- a/fmt.c
+++ b/fmt.c
@@ -182,6 +182,8 @@
return l;
}
+static void fmt_keshideh(struct fmt *f, int beg, int end, int wid);
+
/* extract words from beg to end; shrink or stretch spaces if needed */
static int fmt_extractline(struct fmt *f, int beg, int end, int str)
{
@@ -192,6 +194,10 @@
return 1;
llen = FMT_LLEN(f);
w = fmt_wordslen(f, beg, end);
+ if (str && FMT_ADJ(f) && n_j & AD_K) {
+ fmt_keshideh(f, beg, end, llen - w);
+ w = fmt_wordslen(f, beg, end);
+ }
nspc = fmt_spaces(f, beg, end);
if (nspc && FMT_ADJ(f) && (llen < w || str)) {
fmt_div = (llen - w) / nspc;
@@ -394,6 +400,34 @@
f->nls_sup = 0;
f->gap = 0;
return 0;
+}
+
+/* insert keshideh characters */
+static void fmt_keshideh(struct fmt *f, int beg, int end, int wid)
+{
+ struct wb wb;
+ int kw, i = 0, c = 0;
+ struct word *w;
+ int cnt = 0;
+ do {
+ cnt = 0;
+ for (c = 0; c < 2; c++) {
+ for (i = end - 1 - c; i >= beg; i -= 2) {
+ w = &f->words[i];
+ wb_init(&wb);
+ kw = wb_keshideh(w->s, &wb, wid);
+ if (kw > 0) {
+ free(w->s);
+ w->s = xmalloc(strlen(wb_buf(&wb)) + 1);
+ strcpy(w->s, wb_buf(&wb));
+ w->wid = wb_wid(&wb);
+ wid -= kw;
+ cnt++;
+ }
+ wb_done(&wb);
+ }
+ }
+ } while (cnt);
}
/* approximate 8 * sqrt(cost) */
--- a/roff.h
+++ b/roff.h
@@ -277,6 +277,8 @@
void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m, int *cd);
void wb_fnszset(struct wb *wb, int fn, int sz, int m, int cd);
void wb_flushdir(struct wb *wb);
+void wb_reset(struct wb *wb);
+int wb_keshideh(char *word, struct wb *dst, int wid);
int wb_hywid(struct wb *wb);
int wb_swid(struct wb *wb);
int c_eossent(char *s);
@@ -308,6 +310,7 @@
#define AD_R 2 /* adjust right margin (flag) */
#define AD_B 3 /* adjust both margin (mask) */
#define AD_P 4 /* paragraph-at-once adjustment (flag) */
+#define AD_K 8 /* keshideh adjustment (flag) */
/* line formatting */
struct fmt *fmt_alloc(void);
--- a/tr.c
+++ b/tr.c
@@ -335,6 +335,8 @@
case 'b':
case 'n':
return AD_B;
+ case 'k':
+ return AD_B | AD_K;
}
return def;
}
--- a/wb.c
+++ b/wb.c
@@ -568,3 +568,52 @@
{
return font_swid(dev_font(R_F(wb)), R_S(wb), n_ss);
}
+
+static char *keshideh_chars[] = {
+ "ﺒ", "ﺑ", "ﭙ", "ﭘ", "ﺘ", "ﺗ", "ﺜ", "ﺛ", "ﺴ", "ﺳ",
+ "ﺸ", "ﺷ", "ﻔ", "ﻓ", "ﻘ", "ﻗ", "ﮑ", "ﮐ", "ﮕ", "ﮔ",
+ "ﻤ", "ﻣ", "ﻨ", "ﻧ", "ﻬ", "ﻫ", "ﯿ", "ﯾ",
+};
+
+static int keshideh(char *c)
+{
+ int i;
+ for (i = 0; i < LEN(keshideh_chars); i++)
+ if (!strcmp(keshideh_chars[i], c))
+ return 1;
+ return 0;
+}
+
+/* insert keshideh */
+int wb_keshideh(char *word, struct wb *dst, int wid)
+{
+ char p[GNLEN] = "";
+ char *s, *d, *s_prev = NULL, *s_kesh = NULL;
+ int ins = 0;
+ int c;
+ /* find the last keshideh position */
+ s = word;
+ while ((c = escread(&s, &d)) >= 0) {
+ wb_putc(dst, c, d);
+ if (!c && strcmp("ـ", d) && keshideh(p)) {
+ struct glyph *g = dev_glyph("ـ", R_F(dst));
+ int kw = g ? font_gwid(g->font,
+ dev_font(R_F(dst)), R_S(dst), g->wid) : 0;
+ if (g && kw < wid) {
+ s_kesh = s_prev;
+ ins = kw;
+ }
+ }
+ s_prev = s;
+ strcpy(p, c ? "" : d);
+ }
+ /* insert the keshideh at s_kesh */
+ s = word;
+ wb_reset(dst);
+ while ((c = escread(&s, &d)) >= 0) {
+ wb_putc(dst, c, d);
+ if (s == s_kesh)
+ wb_putc(dst, 0, "ـ");
+ }
+ return ins;
+}