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