1
2 /************************************************************************
3 * *
4 * VIETNAMESE PRE-PROCESSOR FOR TROFF *
5 * *
6 * Written in Pascal by Hu+~u (University of California at Berkeley) *
7 * Converted to C & modified by Tra^`n H. Nha^n (Concurrent Computer) *
8 * *
9 * This program processes a text file with special vietnamese character *
10 * sequences giving an output suitable for troff processing. *
11 * *
12 * The default diacritical marks are define as followed: *
13 * *
14 * #define Dau_Sac '\'' *
15 * #define Dau_Huyen '`' *
16 * #define Dau_Hoi '?' *
17 * #define Dau_Nga '~' *
18 * #define Dau_Nang '.' *
19 * #define Dau_Mu '^' *
20 * #define Dau_Trang '(' *
21 * #define Dau_Rau '+' *
22 * #define Escape_Symbol '\\' *
23 * *
24 * Change them to any symbol you are comfortable with. *
25 * *
26 * Rule for writing Vietnamese: *
27 * *
28 * 1 diacritical mark: vowel followed by symbol, i.e: a' e? o` u~ a^ u+ *
29 * 2 diacritical marks: vowel followed by Dau_Mu, Dau_Trang, Dau_Rau *
30 * then other symbols, i.e: a^' o+~ a(` ... *
31 * *
32 * DD and dd: self-explanatory, the resulting case is the same as the *
33 * first character of [Dd][Dd]. *
34 * *
35 * The Escape_Symbol is provided to avoid the confusion between the *
36 * diacritical marks and end-of-sentence symbols (. ; ? ! ...) *
37 * i.e: the question Anh ddi dda^u? *
38 * should be typed Anh ddi dda^u#? *
39 ************************************************************************/
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 /************************************************************************
46 Customization: substitute your favorite symbol for ' ` ? ~ . ^ ( + #
47 ************************************************************************/
48
49 #define Dau_Sac '\'' /* type ' only not \' */
50 #define Dau_Huyen '`'
51 #define Dau_Hoi '?'
52 #define Dau_Nga '~'
53 #define Dau_Nang '.'
54 #define Dau_Mu '^'
55 #define Dau_Trang '('
56 #define Dau_Rau '+'
57 #define Escape_Symbol '\\'
58
59 #define NON 0 /* ^ as in a^ */
60 #define RAU 1 /* + as in u+, o+ */
61 #define TRANG 2 /* ( as in a( */
62 #define NONE 3 /* no mark */
63 #define II 4 /* specify i, I */
64
65 char List1[] = {Dau_Sac, Dau_Huyen, Dau_Hoi, Dau_Nga, Dau_Nang, '\0'};
66 char List2[] = {Dau_Sac, Dau_Huyen, Dau_Hoi, Dau_Nga, Dau_Nang,
67 Dau_Mu, Dau_Rau, Dau_Trang, '\0'};
68
69 #define Is_Vowel(ch) (strchr("aeiouyAEIOUY",(ch)) != NULL)
70 #define Is_in_list1(ch) (strchr(List1,(ch)) != NULL)
71 #define Is_in_list2(ch) (strchr(List2,(ch)) != NULL)
72
73 float extendUp, extendLeft;
74 FILE *infile;
75
76 /***************************************************************************
77 * Move: This is a basic routine used to move a given symbol around to *
78 * achieve the desired Vietnamese character. *
79 * *
80 * Example: to create a', first print out a, then move the symbol ' *
81 * left 0.5 of m units and up 0 m units. (m is a unit dependent *
82 * on the current point size. Thus the program works for all *
83 * point sizes you specify). If left and up are negative then *
84 * the symbol is moved right and down instead. *
85 ***************************************************************************/
86
Move(left,up,symbol)87 void Move(left,up,symbol)
88 float left,up;
89 int symbol;
90 {
91 if (left+extendLeft != 0)
92 printf("\\h'%.2fm'",-(left+extendLeft));
93 if (up+extendUp != 0)
94 printf("\\v'%.2fm'",-(up+extendUp));
95 switch (symbol) {
96 case Dau_Sac : printf("\\z\\'");
97 break;
98 case Dau_Huyen : printf("\\z\\`");
99 break;
100 case Dau_Hoi : printf("\\z'");
101 break;
102 case Dau_Nga : printf("\\z\\fB~\\fP");
103 break;
104 case Dau_Nang : printf("\\z.");
105 break;
106 case '-' : printf("\\z\\(hy");
107 break;
108 case Dau_Mu : printf("\\z^");
109 break;
110 default : break;
111 }
112 if (up+extendUp != 0)
113 printf("\\v'%.2fm'",up+extendUp);
114 if (left+extendLeft != 0)
115 printf("\\h'%.2fm'",left+extendLeft);
116 }
117
118 /***************************************************************************
119 * Bo_Dau_Sac: Bo? da^'u sa('c for all cases. *
120 ***************************************************************************/
121
Bo_Dau_Sac(l)122 void Bo_Dau_Sac(l)
123 int l;
124 {
125 switch (l) {
126 case NONE : Move(0.5,0.0,Dau_Sac); /* ex: a' e' O' ... */
127 break;
128 case NON : Move(0.4,0.15,Dau_Sac); /* ex: a^' E^' ... */
129 break;
130 case RAU : Move(0.6,0.1,Dau_Sac); /* ex: o+' U+' ... */
131 break;
132 case TRANG : Move(0.5,0.15,Dau_Sac); /* ex: a(' A(' ... */
133 break;
134 case II : Move(0.3,0.15,Dau_Sac); /* ex: i' I' ... */
135 break;
136 default : break;
137 }
138 }
139
140 /***************************************************************************
141 * Bo_Dau_Huyen: Bo? da^'u huye^`n for all cases. *
142 ***************************************************************************/
143
Bo_Dau_Huyen(l)144 void Bo_Dau_Huyen(l)
145 int l;
146 {
147 switch (l) {
148 case NONE : Move(0.5,0.0,Dau_Huyen); /* a` e` O` ... */
149 break;
150 case NON : Move(0.6,0.15,Dau_Huyen); /* a^` E^` ... */
151 break;
152 case II : Move(0.4,0.15,Dau_Huyen); /* i` I` ... */
153 break;
154 case RAU : Move(0.55,0.1,Dau_Huyen); /* u+` O+` ... */
155 break;
156 case TRANG : Move(0.5,0.15,Dau_Huyen); /* a(` A(` ... */
157 break;
158 default : break;
159 }
160 }
161
162 /***************************************************************************
163 * Bo_Dau_Hoi: Bo? da^'u ho?i for all cases. *
164 ***************************************************************************/
165
Bo_Dau_Hoi(l)166 void Bo_Dau_Hoi(l)
167 int l;
168 {
169 switch(l) {
170 case NONE : Move(0.4,0.1,Dau_Hoi); /* a? e? O? ... */
171 break;
172 case NON :
173 case II : Move(0.25,0.2,Dau_Hoi); /* a^? E^? i? I? ... */
174 break;
175 case RAU : Move(0.45,0.15,Dau_Hoi); /* u+? o+? ... */
176 break;
177 case TRANG : Move(0.40,0.15,Dau_Hoi); /* a(? A(? ... */
178 break;
179 default : break;
180 }
181 }
182
183 /***************************************************************************
184 * Bo_Dau_Nga: Bo? da^'u nga~ for all cases. *
185 ***************************************************************************/
186
Bo_Dau_Nga(l)187 void Bo_Dau_Nga(l)
188 int l;
189 {
190 switch (l) {
191 case NONE : Move(0.5,0.0,Dau_Nga); /* a~ e~ O~ ... */
192 break;
193 case NON :
194 case TRANG : Move(0.5,0.15,Dau_Nga); /* a^~ a(~ E^~ ... */
195 break;
196 case RAU : Move(0.55,0.15,Dau_Nga); /* u+~ O+~ ... */
197 break;
198 case II : Move(0.4,0.06,Dau_Nga); /* i~ I~ ... */
199 break;
200 default : break;
201 }
202 }
203
204 /***************************************************************************
205 * Bo_Dau_Nang: Bo? da^'u na(.ng for all cases. *
206 ***************************************************************************/
207
Bo_Dau_Nang(l)208 void Bo_Dau_Nang(l)
209 int l;
210 {
211 extendUp = 0;
212 if (l == II)
213 Move(0.3,-0.2,Dau_Nang); /* i. I. */
214 else
215 Move(0.4,-0.2,Dau_Nang); /* all other cases */
216 }
217
218 /***************************************************************************
219 * Bo_Dau: bo? da^'u cho mo.i tru+o+`ng ho+.p *
220 ***************************************************************************/
221
Bo_Dau(c,nextc,loai)222 void Bo_Dau(c,nextc,loai)
223 int c,nextc,loai;
224 {
225 if (nextc == Dau_Trang)
226 switch (c) { /* create a( A( */
227 case 'a' :
228 case 'A' : putchar(c);
229 getc(infile);
230 loai = TRANG;
231 Move(0.50,-0.1,Dau_Huyen);
232 Move(0.50-0.02,-0.1,Dau_Sac);
233 break;
234 default : break;
235 }
236 else if (nextc == Dau_Rau) /* create o+ u+ O+ U+ */
237 switch (c) {
238 case 'o' :
239 case 'O' :
240 case 'u' :
241 case 'U' : putchar(c);
242 getc(infile);
243 loai = RAU;
244 if (isupper(c))
245 Move(0.2,-0.05,Dau_Hoi);
246 else
247 Move(0.25,-0.1,Dau_Hoi);
248 break;
249 default : break;
250 }
251 else if (nextc == Dau_Mu) /* create a^ e^ o^ A^ E^ O^ */
252 switch (c) {
253 case 'a' :
254 case 'e' :
255 case 'o' : printf("\\o'%c^'",c);
256 getc(infile);
257 loai = NON;
258 break;
259 case 'A' :
260 case 'E' :
261 case 'O' : putchar(c);
262 getc(infile);
263 Move(0.55,0.0,Dau_Mu);
264 loai = NON;
265 break;
266 default : break;
267 }
268 if (Is_in_list1(nextchar())) {
269 c = getc(infile); /* If next char is ' ` ? ~ . */
270 switch(c) { /* then bo? da^'u */
271 case Dau_Sac : Bo_Dau_Sac(loai);
272 break;
273 case Dau_Huyen : Bo_Dau_Huyen(loai);
274 break;
275 case Dau_Hoi : Bo_Dau_Hoi(loai);
276 break;
277 case Dau_Nga : Bo_Dau_Nga(loai);
278 break;
279 case Dau_Nang : Bo_Dau_Nang(loai);
280 break;
281 default : break;
282 }
283 }
284 }
285
286 /***************************************************************************
287 * nextchar(): return next character but leave buffer untouched. *
288 ***************************************************************************/
289
nextchar()290 int nextchar()
291 {
292 int c;
293
294 c = getc(infile);
295 ungetc(c,infile);
296
297 return (c);
298 }
299
300 /***************************************************************************
301 * main: process file *
302 ***************************************************************************/
303
main(argc,argv)304 main(argc, argv)
305 int argc;
306 char *argv[];
307 {
308 int ch,nextch,loai;
309
310 if (argc < 2) {
311 printf("Usage: vnroff filename\n");
312 exit(0);
313 }
314 if ((infile = fopen(argv[1],"r")) == NULL) {
315 printf("Cannot open file %s\n",argv[1]);
316 exit(0);
317 }
318 while ((ch = getc(infile)) != EOF) {
319 extendUp = extendLeft = 0;
320 if (Is_Vowel(ch)) { /* take care vowel */
321 nextch = nextchar();
322 if (Is_in_list2(nextch)) { /* is next char diacritical marks */
323 if (isupper(ch)) {
324 extendUp = 0.2;
325 if (ch != 'I')
326 extendLeft = 0.1;
327 }
328 loai = (ch == 'i' || ch == 'I') ? II : NONE;
329 switch (nextch) {
330 case Dau_Trang :
331 case Dau_Mu :
332 case Dau_Rau : Bo_Dau(ch,nextch,loai);
333 break;
334 case Dau_Sac :
335 case Dau_Huyen :
336 case Dau_Hoi :
337 case Dau_Nga :
338 case Dau_Nang : putchar(ch);
339 Bo_Dau(ch,nextch,loai);
340 break;
341 default : break;
342 }
343 }
344 else
345 putchar(ch);
346 }
347 else if (toupper(ch) == 'D') { /* take care DD, dd */
348 putchar(ch);
349 if (toupper(nextchar()) == toupper(ch)) {
350 getc(infile);
351 if (ch == 'd')
352 Move(0.30,0.35,'-');
353 else
354 Move(0.70,0.15,'-');
355 }
356 }
357 else if (ch == Escape_Symbol) /* print next char as is */
358 putchar(getc(infile));
359 else /* print all other char */
360 putchar(ch);
361 }
362 }
363
364
365