1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "dict.h"
5
6 /* Possible tags */
7 enum {
8 BEG, /* beginning of entry */
9 AB, /* abstract */
10 AN, /* database serial number */
11 AS, /* author (one at a time) */
12 AU, /* all authors */
13 AW, /* award_awardee */
14 BW, /* bw or c */
15 CA, /* cast: character_actor */
16 CN, /* cinematography */
17 CO, /* country */
18 CR, /* miscellaneous job_name */
19 DE, /* topic keyword */
20 DR, /* director */
21 ED, /* editor */
22 MP, /* MPAA rating (R, PG, etc.) */
23 NT, /* note */
24 PR, /* producer and for ...*/
25 PS, /* producer (repeats info in PR) */
26 RA, /* rating (letter) */
27 RD, /* release date */
28 RT, /* running time */
29 RV, /* review citation */
30 ST, /* production or release company (repeats info in PR) */
31 TI, /* title[; original foreign title] */
32 TX, /* paragraph of descriptive text */
33 VD, /* video information (format_time_company; or "Not Avail.") */
34 NTAG /* number of tags */
35 };
36
37 /* Assoc tables must be sorted on first field */
38
39 static char *tagtab[] = {
40 [BEG] "$$",
41 [AB] "AB",
42 [AN] "AN",
43 [AS] "AS",
44 [AU] "AU",
45 [AW] "AW",
46 [BW] "BW",
47 [CA] "CA",
48 [CN] "CN",
49 [CO] "CO",
50 [CR] "CR",
51 [DE] "DE",
52 [DR] "DR",
53 [ED] "ED",
54 [MP] "MP",
55 [NT] "NT",
56 [PR] "PR",
57 [PS] "PS",
58 [RA] "RA",
59 [RD] "RD",
60 [RT] "RT",
61 [RV] "RV",
62 [ST] "ST",
63 [TI] "TI",
64 [TX] "TX",
65 [VD] "VD",
66 };
67
68 static char *mget(int, char *, char *, char **);
69 static void moutall(int, char *, char *);
70 static void moutall2(int, char *, char *);
71
72 void
movieprintentry(Entry ent,int cmd)73 movieprintentry(Entry ent, int cmd)
74 {
75 char *p, *e, *ps, *pe, *pn;
76 int n;
77
78 ps = ent.start;
79 pe = ent.end;
80 if(cmd == 'r') {
81 Bwrite(bout, ps, pe-ps);
82 return;
83 }
84 p = mget(TI, ps, pe, &e);
85 if(p) {
86 outpiece(p, e);
87 outnl(0);
88 }
89 if(cmd == 'h')
90 return;
91 outnl(2);
92 n = 0;
93 p = mget(RD, ps, pe, &e);
94 if(p) {
95 outchars("Released: ");
96 outpiece(p, e);
97 n++;
98 }
99 p = mget(CO, ps, pe, &e);
100 if(p) {
101 if(n)
102 outchars(", ");
103 outpiece(p, e);
104 n++;
105 }
106 p = mget(RT, ps, pe, &e);
107 if(p) {
108 if(n)
109 outchars(", ");
110 outchars("Running time: ");
111 outpiece(p, e);
112 n++;
113 }
114 p = mget(MP, ps, pe, &e);
115 if(p) {
116 if(n)
117 outchars(", ");
118 outpiece(p, e);
119 n++;
120 }
121 p = mget(BW, ps, pe, &e);
122 if(p) {
123 if(n)
124 outchars(", ");
125 if(*p == 'c' || *p == 'C')
126 outchars("Color");
127 else
128 outchars("B&W");
129 n++;
130 }
131 if(n) {
132 outchar('.');
133 outnl(1);
134 }
135 p = mget(VD, ps, pe, &e);
136 if(p) {
137 outchars("Video: ");
138 outpiece(p, e);
139 outnl(1);
140 }
141 p = mget(AU, ps, pe, &e);
142 if(p) {
143 outchars("By: ");
144 moutall2(AU, ps, pe);
145 outnl(1);
146 }
147 p = mget(DR, ps, pe, &e);
148 if(p) {
149 outchars("Director: ");
150 outpiece(p, e);
151 outnl(1);
152 }
153 p = mget(PR, ps, pe, &e);
154 if(p) {
155 outchars("Producer: ");
156 outpiece(p, e);
157 outnl(1);
158 }
159 p = mget(CN, ps, pe, &e);
160 if(p) {
161 outchars("Cinematograpy: ");
162 outpiece(p, e);
163 outnl(1);
164 }
165 p = mget(CR, ps, pe, &e);
166 if(p) {
167 outchars("Other Credits: ");
168 moutall2(CR, ps, pe);
169 }
170 outnl(2);
171 p = mget(CA, ps, pe, &e);
172 if(p) {
173 outchars("Cast: ");
174 moutall2(CA, ps, pe);
175 }
176 outnl(2);
177 p = mget(AW, ps, pe, &e);
178 if(p) {
179 outchars("Awards: ");
180 moutall2(AW, ps, pe);
181 outnl(2);
182 }
183 p = mget(NT, ps, pe, &e);
184 if(p) {
185 outpiece(p, e);
186 outnl(2);
187 }
188 p = mget(AB, ps, pe, &e);
189 if(p) {
190 outpiece(p, e);
191 outnl(2);
192 }
193 pn = ps;
194 n = 0;
195 while((p = mget(TX, pn, pe, &pn)) != 0) {
196 if(n++)
197 outnl(1);
198 outpiece(p, pn);
199 }
200 outnl(0);
201 }
202
203 long
movienextoff(long fromoff)204 movienextoff(long fromoff)
205 {
206 long a;
207 char *p;
208
209 a = Bseek(bdict, fromoff, 0);
210 if(a < 0)
211 return -1;
212 for(;;) {
213 p = Brdline(bdict, '\n');
214 if(!p)
215 break;
216 if(p[0] == '$' && p[1] == '$')
217 return (Boffset(bdict)-Blinelen(bdict));
218 }
219 return -1;
220 }
221
222 void
movieprintkey(void)223 movieprintkey(void)
224 {
225 Bprint(bout, "No key\n");
226 }
227
228 /*
229 * write a comma-separated list of all tag values between b and e
230 */
231 static void
moutall(int tag,char * b,char * e)232 moutall(int tag, char *b, char *e)
233 {
234 char *p, *pn;
235 int n;
236
237 n = 0;
238 pn = b;
239 while((p = mget(tag, pn, e, &pn)) != 0) {
240 if(n++)
241 outchars(", ");
242 outpiece(p, pn);
243 }
244 }
245
246 /*
247 * like moutall, but values are expected to have form:
248 * field1_field2
249 * and we are to output 'field2 (field1)' for each
250 * (sometimes field1 has underscores, so search from end)
251 */
252 static void
moutall2(int tag,char * b,char * e)253 moutall2(int tag, char *b, char *e)
254 {
255 char *p, *pn, *us, *q;
256 int n;
257
258 n = 0;
259 pn = b;
260 while((p = mget(tag, pn, e, &pn)) != 0) {
261 if(n++)
262 outchars(", ");
263 us = 0;
264 for(q = pn-1; q >= p; q--)
265 if(*q == '_') {
266 us = q;
267 break;
268 }
269 if(us) {
270 /*
271 * Hack to fix cast list Himself/Herself
272 */
273 if(strncmp(us+1, "Himself", 7) == 0 ||
274 strncmp(us+1, "Herself", 7) == 0) {
275 outpiece(p, us);
276 outchars(" (");
277 outpiece(us+1, pn);
278 outchar(')');
279 } else {
280 outpiece(us+1, pn);
281 outchars(" (");
282 outpiece(p, us);
283 outchar(')');
284 }
285 } else {
286 outpiece(p, pn);
287 }
288 }
289 }
290
291 /*
292 * Starting from b, find next line beginning with tagtab[tag].
293 * Don't go past e, but assume *e==0.
294 * Return pointer to beginning of value (after tag), and set
295 * eptr to point at newline that ends the value
296 */
297 static char *
mget(int tag,char * b,char * e,char ** eptr)298 mget(int tag, char *b, char *e, char **eptr)
299 {
300 char *p, *t, *ans;
301
302 if(tag < 0 || tag >= NTAG)
303 return 0;
304 t = tagtab[tag];
305 ans = 0;
306 for(p = b;;) {
307 p = strchr(p, '\n');
308 if(!p || ++p >= e) {
309 if(ans)
310 *eptr = e-1;
311 break;
312 }
313 if(!ans) {
314 if(p[0] == t[0] && p[1] == t[1])
315 ans = p+3;
316 } else {
317 if(p[0] != ' ') {
318 *eptr = p-1;
319 break;
320 }
321 }
322 }
323 return ans;
324 }
325