1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5
6 /* convert a hex string to an array of ints */
7
8 int*
hex_to_array(str)9 hex_to_array(str)
10 char* str;
11 {
12 int *a;
13 int i, j, n, v;
14
15 n = strlen(str) / 8;
16 New(0, a, n, int);
17 for (i = 0; i < n; i++) {
18 v = 0;
19 for (j = 0; j < 8; j++) {
20 v = v << 4;
21 if (str[i*8 + j] >= 'a') {
22 v = v + str[i*8 + j] - 'a' + 10;
23 } else {
24 v = v + str[i*8 + j] - '0';
25 }
26 }
27 a[i] = v;
28 }
29 return(a);
30 }
31
32
33 /* Pack an array of ints into a hex string */
34
35 char*
array_to_hex(a,n)36 array_to_hex(a, n)
37 int* a;
38 int n;
39 {
40 char *res;
41 char s[9];
42 int i;
43
44 New(0, res, n * 8 + 1, char);
45 res[0] = 0;
46 for (i = 0; i < n; i++) {
47 sprintf(s, "%08x", a[i]);
48 strcat(res, s);
49 }
50 return(res);
51 }
52
53
54 char*
reflow_trial(optimum_c,maximum,wordcount,penaltylimit,semantic,shortlast,word_len_c,space_len_c,extra_c,result)55 reflow_trial(optimum_c, maximum, wordcount,
56 penaltylimit, semantic, shortlast,
57 word_len_c, space_len_c, extra_c,
58 result)
59 int maximum, wordcount, penaltylimit, semantic, shortlast;
60 char *optimum_c, *word_len_c, *space_len_c, *extra_c;
61 char *result;
62 {
63 int *optimum, *word_len, *space_len, *extra;
64
65 int *linkbreak, *totalpenalty, *best_linkbreak;
66 int lastbreak, i, j, k, interval, penalty, bestsofar;
67 int best_lastbreak, opt;
68 char *best_linkbreak_c;
69 int opts, ii, count;
70 int best = penaltylimit * 21;
71
72 optimum = hex_to_array(optimum_c);
73 word_len = hex_to_array(word_len_c);
74 space_len = hex_to_array(space_len_c);
75 extra = hex_to_array(extra_c);
76
77 count = wordcount * sizeof(int);
78 New(0, linkbreak, count, int);
79 New(0, totalpenalty, count, int);
80 New(0, best_linkbreak, count, int);
81
82 /* Keep gcc -Wall happy: */
83 best_lastbreak = 0;
84
85 /* size of optimum array: */
86 opts = strlen(optimum_c) / 8;
87
88 for (i = 0; i < opts; i++) {
89 opt = optimum[i];
90 for (j = 0; j < wordcount; j++) {
91 interval = 0;
92 totalpenalty[j] = penaltylimit * 2;
93 for (k = j; k >= 0; k--) {
94 interval += word_len[k];
95 if ((k < j) && ((interval > opt + 10)
96 || (interval >= maximum))) {
97 break;
98 }
99 penalty = (interval - opt) * (interval - opt);
100 interval += space_len[k];
101 if (k > 0) {
102 penalty += totalpenalty[k-1];
103 }
104 penalty -= (extra[j] * semantic)/2;
105 if (penalty < totalpenalty[j]) {
106 totalpenalty[j] = penalty;
107 linkbreak[j] = k-1;
108 }
109 }
110 }
111 interval = 0;
112 bestsofar = penaltylimit * 20;
113 lastbreak = wordcount-2;
114 /* Pick a break for the last line which gives */
115 /* the least penalties for previous lines: */
116 for (k = wordcount-2; k >= -1; k--) {
117 interval += word_len[k+1];
118 if ((interval > opt + 10) || (interval > maximum)) {
119 break;
120 }
121 if (interval > opt) {
122 penalty = (interval - opt) * (interval - opt);
123 } else {
124 penalty = 0;
125 }
126 interval += space_len[k+1];
127 if (k >= 0) {
128 penalty += totalpenalty[k];
129 }
130 if (wordcount - k - 1 <= 2) {
131 penalty += shortlast * semantic;
132 }
133 if (penalty <= bestsofar) {
134 bestsofar = penalty;
135 lastbreak = k;
136 }
137 }
138 /* Save these breaks if they are an improvement: */
139 if (bestsofar < best) {
140 best_lastbreak = lastbreak;
141 for (ii = 0; ii < wordcount; ii++) {
142 best_linkbreak[ii] = linkbreak[ii];
143 }
144 best = bestsofar;
145 }
146 }
147
148 /* Return the best breaks, */
149 /* ie return the array ($best_lastbreak, @best_linkbreak) as a hex string */
150 best_linkbreak_c = array_to_hex(best_linkbreak, wordcount);
151 sprintf(result, "%08x", best_lastbreak);
152 strcat(result, best_linkbreak_c);
153
154 Safefree(optimum);
155 Safefree(word_len);
156 Safefree(space_len);
157 Safefree(extra);
158 Safefree(linkbreak);
159 Safefree(totalpenalty);
160 Safefree(best_linkbreak);
161 Safefree(best_linkbreak_c);
162
163 return(result);
164 }
165
166
167
168 MODULE = Text::Reflow PACKAGE = Text::Reflow
169
170
171 char *
172 reflow_trial(optimum, maximum, wordcount, \
173 penaltylimit, semantic, shortlast, \
174 word_len, space_len, extra, result)
175 int maximum
176 int wordcount
177 int penaltylimit
178 int semantic
179 int shortlast
180 char* optimum
181 char* word_len
182 char* space_len
183 char* extra
184 char* result
185 PROTOTYPE: $$$$$$$$$$
186 OUTPUT:
187 result
188
189
190