1 /*
2 * xvtext.c - text file display window routines
3 *
4 * includes:
5 * void CreateTextWins(geom, cmtgeom);
6 * void OpenTextView(text, textlen, title, freeonclose);
7 * void OpenCommentText();
8 * void CloseCommentText();
9 * void ChangeCommentText();
10 * void HideTextWindows();
11 * void UnHideTextWindows();
12 * void RaiseTextWindows();
13 * void SetTextCursor(Cursor);
14 * void KillTextWindows();
15 * int TextCheckEvent(evt, int *retval, int *done);
16 *
17 */
18
19 #include "copyright.h"
20
21 #include "xv.h"
22 #ifdef TV_MULTILINGUAL
23 #include "xvml.h"
24 #endif
25
26 #define BUTTW1 80
27 #define BUTTW2 60
28 #define BUTTW3 110
29 #define BUTTH 24
30
31 #define TOPMARGIN 30 /* from top of window to top of text window */
32 #define BOTMARGIN (5+BUTTH+5) /* room for a row of buttons at bottom */
33 #define LRMARGINS 5 /* left and right margins */
34
35 #define MAXTVWIN 2 /* total # of windows */
36 #define MAXTEXTWIN 1 /* # of windows for text file viewing */
37 #define CMTWIN 1 /* cmtwin is reserved for image comments */
38
39 /* button/menu indicies */
40 #define TV_ASCII 0
41 #define TV_HEX 1
42 #define TV_CLOSE 2
43
44 #define TV_E_NBUTTS 3
45
46 #ifdef TV_L10N
47 # define TV_RESCAN 3
48 # define TV_USASCII 4
49 # define TV_JIS 5
50 # define TV_EUCJ 6
51 # define TV_MSCODE 7
52
53 # define TV_J_NBUTTS 8
54 #endif
55
56 #define TITLELEN 128
57
58 #ifdef TV_MULTILINGUAL
59 struct coding_spec {
60 struct coding_system coding_system;
61 char *(*converter)PARM((char *, int, int *));
62 };
63 #endif
64
65 /* data needed per text window */
66 typedef struct { Window win, textW;
67 int vis, wasvis;
68 const char *text; /* text to be displayed */
69 int freeonclose; /* free text when closing win */
70 int textlen; /* length of text */
71 char title[TITLELEN]; /* name of file being displayed */
72 const char **lines; /* ptr to array of line ptrs */
73 int numlines; /* # of lines in text */
74 int hexlines; /* # of lines in HEX mode */
75 int maxwide; /* length of longest line (ascii) */
76 int wide, high; /* size of outer window (win) */
77 int twWide, twHigh; /* size of inner window (textW) */
78 int chwide, chhigh; /* size of textW, in chars */
79 int hexmode; /* true if disp Hex, else Ascii */
80 SCRL vscrl, hscrl;
81 #ifdef TV_L10N
82 int code; /* current character code */
83 BUTT but[TV_J_NBUTTS], nopBut;
84 #else
85 BUTT but[TV_E_NBUTTS], nopBut;
86 #endif
87 #ifdef TV_MULTILINGUAL
88 /* int codeset; */
89 struct coding_spec ccs; /* current coding_spec */
90 BUTT csbut;
91 char *cv_text;
92 int cv_len;
93 struct context *ctx;
94 struct ml_text *txt;
95 struct csinfo_t *cs;
96 #endif
97 } TVINFO;
98
99
100 static TVINFO tinfo[MAXTVWIN];
101 static int hasBeenSized = 0;
102 static int haveWindows = 0;
103 static int nbutts; /* # of buttons */
104 static int mfwide, mfhigh, mfascent; /* size of chars in mono font */
105 static int *event_retP, *event_doneP; /* used in tvChkEvent() */
106 #ifdef TV_MULTILINGUAL
107 # define TV_PLAIN 0
108 # define TV_ISO_8859_1 1
109 # define TV_ISO_2022_JP 2
110 # define TV_EUC_JAPAN 3
111 # define TV_ISO_2022_INT_1 4
112 # define TV_ISO_2022_KR 5
113 # define TV_EUC_KOREA 6
114 # define TV_ISO_2022_SS2_8 7
115 # define TV_ISO_2022_SS2_7 8
116 # define TV_SHIFT_JIS 9
117 # define TV_NCSS 10
118 static char *codeSetNames[TV_NCSS] = {
119 "plain",
120 "iso-8859-1",
121 "iso-2022-jp",
122 "euc-japan",
123 "iso-2022-int-1",
124 "iso-2022-kr",
125 "euc-korea",
126 "iso-2022-ss2-8",
127 "iso-2022-ss2-7",
128 "Shift JIS",
129 };
130 static struct coding_spec coding_spec[TV_NCSS] = {
131 /* --- G0 --- --- G1 --- --- G2 --- --- G3 --- GL GR EOL SF LS */
132 /* plain */
133 {{{{ 1,94,'B'}, { 1,94,'B'}, { 1,94,'B'}, { 1,94,'B'}}, 0, 0, 0, 1, 1},
134 NULL},
135 /* iso-8859-1 */
136 {{{{ 1,94,'B'}, { 1,96,'A'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 0, 0},
137 NULL},
138 /* iso-2022-jp */
139 {{{{ 1,94,'B'}, {-1,94,'B'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 0, 0, 1, 0},
140 NULL},
141 /* euc-japan */
142 {{{{ 1,94,'B'}, { 2,94,'B'}, { 1,94,'J'}, { 2,94,'D'}}, 0, 1, 0, 1, 0},
143 NULL},
144 /* iso-2022-int-1 */
145 {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 1, 1},
146 NULL},
147 /* iso-2022-kr */
148 {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 0, 1},
149 NULL},
150 /* euc-korea */
151 {{{{ 1,94,'B'}, { 2,94,'C'}, {-1,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 0, 0},
152 NULL},
153 /* iso-2022-ss2-8 */
154 {{{{ 1,94,'B'}, {-1,94,'C'}, { 0,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 0, 0},
155 NULL},
156 /* iso-2022-ss2-7 */
157 {{{{ 1,94,'B'}, {-1,94,'C'}, { 0,94,'B'}, {-1,94,'B'}}, 0, 1, 0, 1, 0},
158 NULL},
159 /* shift jis */
160 {{{{ 1,94,'B'}, { 2,94,'B'}, { 1,94,'J'}, { 2,94,'D'}}, 0, 1, 1, 1, 0},
161 sjis_to_jis},
162 };
163 #endif
164
165 static void closeText PARM((TVINFO *));
166 static int tvChkEvent PARM((TVINFO *, XEvent *));
167 static void resizeText PARM((TVINFO *, int, int));
168 static void computeScrlVals PARM((TVINFO *));
169 static void doCmd PARM((TVINFO *, int));
170 static void drawTextView PARM((TVINFO *));
171 static void drawNumLines PARM((TVINFO *));
172 static void eraseNumLines PARM((TVINFO *));
173 static void drawTextW PARM((int, SCRL *));
174 static void clickText PARM((TVINFO *, int, int));
175 static void keyText PARM((TVINFO *, XKeyEvent *));
176 static void textKey PARM((TVINFO *, int));
177 static void doHexAsciiCmd PARM((TVINFO *, int));
178 static void computeText PARM((TVINFO *));
179 #ifdef TV_L10N
180 static int selectCodeset PARM((TVINFO *));
181 #endif
182 #ifdef TV_MULTILINGUAL
183 static void setCodingSpec PARM((TVINFO *, struct coding_spec *));
184 static void createCsWins PARM((const char *));
185 static void openCsWin PARM((TVINFO *));
186 static void closeCsWin PARM((TVINFO *));
187 #endif
188
189 /* HEXMODE output looks like this:
190 0x00000000: 00 11 22 33 44 55 66 77 - 88 99 aa bb cc dd ee ff 0123456789abcdef
191 0x00000010: 00 11 22 33 44 55 66 77 - 88 99 aa bb cc dd ee ff 0123456789abcdef
192 etc.
193 */
194
195 /***************************************************************/
CreateTextWins(geom,cmtgeom)196 void CreateTextWins(geom, cmtgeom)
197 const char *geom, *cmtgeom;
198 {
199 int i, defwide, defhigh, cmthigh;
200 XSizeHints hints;
201 XSetWindowAttributes xswa;
202 TVINFO *tv;
203 #ifdef TV_MULTILINGUAL
204 int default_codeset;
205 #endif
206
207 #ifdef TV_L10N
208 if (!xlocale) {
209 #endif
210 mfwide = monofinfo->max_bounds.width;
211 mfhigh = monofinfo->ascent + monofinfo->descent;
212 mfascent = monofinfo->ascent;
213
214 nbutts = TV_E_NBUTTS; /* # of buttons */
215 #ifdef TV_L10N
216 }
217 else {
218 mfwide = monofsetinfo->max_logical_extent.width / 2; /* shit! */
219 mfhigh = monofsetinfo->max_logical_extent.height + 1;
220 mfascent = mfhigh;
221
222 nbutts = TV_J_NBUTTS; /* # of buttons */
223 }
224 #endif
225
226 #ifdef TV_MULTILINGUAL
227 {
228 char *dc = XGetDefault(theDisp, "xv", "codeSet");
229 if (dc == NULL)
230 default_codeset = TV_DEFAULT_CODESET;
231 else {
232 for (i = 0; i < TV_NCSS; i++) {
233 if (strcmp(dc, codeSetNames[i]) == 0)
234 break;
235 }
236 if (i >= TV_NCSS) {
237 if (strcmp(dc, "iso-2022") == 0)
238 default_codeset = TV_PLAIN;
239 else {
240 SetISTR(ISTR_WARNING, "%s: unknown codeset.", dc);
241 default_codeset = TV_PLAIN;
242 }
243 } else
244 default_codeset = i;
245 }
246 }
247 #endif
248 /* compute default size of textview windows. should be big enough to
249 hold an 80x24 text window */
250
251 defwide = 80 * mfwide + 2*LRMARGINS + 8 + 20; /* -ish */
252 defhigh = 24 * mfhigh + TOPMARGIN + BOTMARGIN + 8 + 20; /* ish */
253 cmthigh = 6 * mfhigh + TOPMARGIN + BOTMARGIN + 8 + 20; /* ish */
254
255 /* creates *all* textview windows at once */
256
257 for (i=0; i<MAXTVWIN; i++) tinfo[i].win = (Window) NULL;
258
259 for (i=0; i<MAXTVWIN; i++) {
260 tv = &tinfo[i];
261
262 #ifdef TV_MULTILINGUAL
263 tv->ctx = ml_create_context(ScreenOfDisplay(theDisp, theScreen));
264 tv->txt = NULL;
265 tv->cv_text = NULL;
266 tv->cv_len = 0;
267 ml_set_charsets(tv->ctx, &coding_spec[TV_PLAIN].coding_system);
268 #endif
269
270 tv->win = CreateWindow((i<CMTWIN) ? "xv text viewer" : "xv image comments",
271 "XVtextview",
272 (i<CMTWIN) ? geom : cmtgeom,
273 defwide,
274 (i<CMTWIN) ? defhigh : cmthigh,
275 infofg, infobg, 1);
276 if (!tv->win) FatalError("can't create textview window!");
277
278 haveWindows = 1;
279 tv->vis = tv->wasvis = 0;
280
281 if (ctrlColor) XSetWindowBackground(theDisp, tv->win, locol);
282 else XSetWindowBackgroundPixmap(theDisp, tv->win, grayTile);
283
284 /* note: everything is sized and positioned in resizeText() */
285
286 tv->textW = XCreateSimpleWindow(theDisp, tv->win, 1,1, 100,100,
287 1,infofg,infobg);
288 if (!tv->textW) FatalError("can't create textview text window!");
289
290 SCCreate(&(tv->vscrl), tv->win, 0,0, 1,100, 0,0,0,0,
291 infofg, infobg, hicol, locol, drawTextW);
292
293 SCCreate(&(tv->hscrl), tv->win, 0,0, 0,100, 0,0,0,0,
294 infofg, infobg, hicol, locol, drawTextW);
295
296 if (XGetNormalHints(theDisp, tv->win, &hints))
297 hints.flags |= PMinSize;
298 else
299 hints.flags = PMinSize;
300
301 hints.min_width = 380;
302 hints.min_height = 200;
303 XSetNormalHints(theDisp, tv->win, &hints);
304
305
306 #ifdef BACKING_STORE
307 xswa.backing_store = WhenMapped;
308 XChangeWindowAttributes(theDisp, tv->textW, CWBackingStore, &xswa);
309 #endif
310
311 XSelectInput(theDisp, tv->textW, ExposureMask | ButtonPressMask);
312
313
314 BTCreate(&(tv->but[TV_ASCII]), tv->win, 0,0,BUTTW1,BUTTH,
315 "Ascii",infofg,infobg,hicol,locol);
316 BTCreate(&(tv->but[TV_HEX]), tv->win, 0,0,BUTTW1,BUTTH,
317 "Hex",infofg,infobg,hicol,locol);
318 BTCreate(&(tv->but[TV_CLOSE]), tv->win, 0,0,BUTTW1,BUTTH,
319 "Close",infofg,infobg,hicol,locol);
320
321 #ifdef TV_L10N
322 if (xlocale) {
323 BTCreate(&(tv->but[TV_RESCAN]), tv->win, 0,0,BUTTW2,BUTTH,
324 "RESCAN",infofg,infobg,hicol,locol);
325 BTCreate(&(tv->but[TV_USASCII]), tv->win, 0,0,BUTTW2,BUTTH,
326 "ASCII",infofg,infobg,hicol,locol);
327 BTCreate(&(tv->but[TV_JIS]), tv->win, 0,0,BUTTW2,BUTTH,
328 "JIS",infofg,infobg,hicol,locol);
329 BTCreate(&(tv->but[TV_EUCJ]), tv->win, 0,0,BUTTW2,BUTTH,
330 "EUC-j",infofg,infobg,hicol,locol);
331 BTCreate(&(tv->but[TV_MSCODE]), tv->win, 0,0,BUTTW2,BUTTH,
332 "MS Kanji",infofg,infobg,hicol,locol);
333 }
334 #endif
335
336 BTCreate(&(tv->nopBut), tv->win, 0,0, (u_int) tv->vscrl.tsize+1,
337 (u_int) tv->vscrl.tsize+1, "", infofg, infobg, hicol, locol);
338 tv->nopBut.active = 0;
339
340 XMapSubwindows(theDisp, tv->win);
341
342 #ifdef TV_MULTILINGUAL
343 BTCreate(&tv->csbut, tv->win, 0, 0, BUTTW1, BUTTH, "Code Sets",
344 infofg, infobg, hicol, locol);
345 #endif
346
347 tv->text = (char *) NULL;
348 tv->textlen = 0;
349 tv->title[0] = '\0';
350 #ifdef TV_L10N
351 tv->code = (xlocale ? LOCALE_DEFAULT : 0);
352 #endif
353 #ifdef TV_MULTILINGUAL
354 tv->ccs = coding_spec[default_codeset];
355 #endif
356 }
357 #ifdef TV_MULTILINGUAL
358 get_monofont_size(&mfwide, &mfhigh);
359 /* recalculate sizes. */
360 defwide = 80 * mfwide + 2*LRMARGINS + 8 + 20; /* -ish */
361 defhigh = 24 * mfhigh + TOPMARGIN + BOTMARGIN + 8 + 20; /* ish */
362 cmthigh = 6 * mfhigh + TOPMARGIN + BOTMARGIN + 8 + 20; /* ish */
363 #endif
364
365 for (i=0; i<MAXTVWIN; i++) {
366 resizeText(&tinfo[i], defwide, (i<CMTWIN) ? defhigh : cmthigh);
367
368 XSelectInput(theDisp, tinfo[i].win, ExposureMask | ButtonPressMask |
369 KeyPressMask | StructureNotifyMask);
370 }
371
372 hasBeenSized = 1; /* we can now start looking at textview events */
373
374 #ifdef TV_MULTILINGUAL
375 createCsWins("+100+100");
376 #endif
377 }
378
379
380 /***************************************************************/
TextView(fname)381 int TextView(fname)
382 const char *fname;
383 {
384 /* given a filename, attempts to read in the file and open a textview win */
385
386 int filetype;
387 long textlen;
388 char *text, buf[512], title[128], rfname[MAXPATHLEN+1];
389 char *basefname[128]; /* just current fname, no path */
390 FILE *fp;
391 char filename[MAXPATHLEN+1];
392
393 strncpy(filename, fname, sizeof(filename) - 1);
394 #ifdef AUTO_EXPAND
395 Mkvdir(filename);
396 Dirtovd(filename);
397 #endif
398
399 basefname[0] = '\0';
400 strncpy(rfname, filename, sizeof(rfname) - 1);
401
402 /* see if this file is compressed. if it is, uncompress it, and view
403 the uncompressed version */
404
405 filetype = ReadFileType(filename);
406 if ((filetype == RFT_COMPRESS) || (filetype == RFT_BZIP2)) {
407 #ifndef VMS
408 if (!UncompressFile(filename, rfname, filetype)) return FALSE;
409 #else
410 /* chop off trailing '.Z' from friendly displayed basefname, if any */
411 strncpy (basefname, filename, 128 - 1);
412 *rindex (basefname, '.') = '\0';
413 if (!UncompressFile(basefname, rfname, filetype)) return FALSE;
414 #endif
415 }
416
417 fp = fopen(rfname, "r");
418 if (!fp) {
419 sprintf(buf,"Couldn't open '%s': %s", rfname, ERRSTR(errno));
420 ErrPopUp(buf,"\nOh well");
421 return FALSE;
422 }
423
424
425 fseek(fp, 0L, 2);
426 textlen = ftell(fp);
427 fseek(fp, 0L, 0);
428
429 if (!textlen) {
430 sprintf(buf, "File '%s' contains no data. (Zero length file.)", rfname);
431 ErrPopUp(buf, "\nOk");
432 fclose(fp);
433 return FALSE;
434 }
435
436 text = (char *) malloc((size_t) textlen + 1);
437 if (!text) {
438 sprintf(buf, "Couldn't malloc %ld bytes to read file '%s'",
439 textlen, rfname);
440 ErrPopUp(buf, "\nSo what!");
441 fclose(fp);
442 return FALSE;
443 }
444
445 if (fread(text, (size_t) 1, (size_t) textlen, fp) != textlen) {
446 sprintf(buf, "Warning: Couldn't read all of '%s'. Possibly truncated.",
447 rfname);
448 ErrPopUp(buf, "\nHmm...");
449 }
450 #ifdef TV_MULTILINGUAL
451 text[textlen] = '\0';
452 #endif
453
454 fclose(fp);
455
456 sprintf(title, "File: '%s'", BaseName(fname));
457 OpenTextView(text, (int) textlen, title, 1);
458
459 /* note: text gets freed when window gets closed */
460 return TRUE;
461 }
462
463
464
465 /***************************************************************/
OpenTextView(text,len,title,freeonclose)466 void OpenTextView(text, len, title, freeonclose)
467 const char *text, *title;
468 int len, freeonclose;
469 {
470 /* opens up a textview window */
471
472 TVINFO *tv;
473
474 tv = &tinfo[0];
475
476 /* kill off old text info */
477 if (tv->freeonclose && tv->text) free((void *)tv->text);
478 if (tv->lines) free(tv->lines);
479
480 tv->text = (const char *) NULL;
481 tv->lines = (const char **) NULL;
482 tv->numlines = tv->textlen = tv->hexmode = 0;
483
484
485 tv->text = text;
486 tv->textlen = len;
487 tv->freeonclose = freeonclose;
488 strncpy(tv->title, title, (size_t) TITLELEN-1);
489 tv->title[TITLELEN-1] = '\0';
490
491 computeText(tv); /* compute # lines and linestarts array */
492
493 anyTextUp = 1;
494 if (!tv->vis) XMapRaised(theDisp, tv->win);
495 else {
496 XClearArea(theDisp, tv->win, 0, 0, (u_int) tv->wide, (u_int) 30, False);
497 drawTextView(tv);
498 }
499 tv->vis = 1;
500
501 SCSetVal(&(tv->vscrl), 0);
502 SCSetVal(&(tv->hscrl), 0);
503 computeScrlVals(tv);
504 }
505
506
507
508 /***************************************************************/
OpenCommentText()509 void OpenCommentText()
510 {
511 /* opens up the reserved 'comment' textview window */
512
513 TVINFO *tv;
514
515 tv = &tinfo[CMTWIN];
516 commentUp = 1;
517 XMapRaised(theDisp, tv->win);
518 tv->vis = 1;
519
520 ChangeCommentText();
521 }
522
523
524 /***************************************************************/
CloseCommentText()525 void CloseCommentText()
526 {
527 /* closes the reserved 'comment' textview window */
528
529 closeText(&tinfo[CMTWIN]);
530 commentUp = 0;
531 }
532
533
534 /***************************************************************/
ChangeCommentText()535 void ChangeCommentText()
536 {
537 /* called when 'picComments' changes */
538
539 TVINFO *tv;
540
541 tv = &tinfo[CMTWIN];
542
543 tv->text = picComments;
544 tv->textlen = (tv->text) ? strlen(tv->text) : 0;
545 tv->freeonclose = 0;
546
547 if (strlen(fullfname))
548 sprintf(tv->title, "File: '%s'", BaseName(fullfname));
549 else
550 sprintf(tv->title, "<no file loaded>");
551
552 computeText(tv); /* compute # lines and linestarts array */
553
554 if (tv->vis) {
555 XClearArea(theDisp, tv->win, 0, 0, (u_int) tv->wide, (u_int) 30, False);
556 drawTextView(tv);
557 }
558
559 SCSetVal(&(tv->vscrl), 0);
560 SCSetVal(&(tv->hscrl), 0);
561
562 computeScrlVals(tv);
563 }
564
565
566 /***************************************************************/
HideTextWindows()567 void HideTextWindows()
568 {
569 int i;
570
571 for (i=0; i<MAXTVWIN; i++) {
572 if (tinfo[i].vis) {
573 XUnmapWindow(theDisp, tinfo[i].win);
574 tinfo[i].wasvis = 1;
575 tinfo[i].vis = 0;
576 }
577 }
578 }
579
580
581 /***************************************************************/
UnHideTextWindows()582 void UnHideTextWindows()
583 {
584 int i;
585
586 for (i=0; i<MAXTVWIN; i++) {
587 if (tinfo[i].wasvis) {
588 XMapRaised(theDisp, tinfo[i].win);
589 tinfo[i].wasvis = 0;
590 tinfo[i].vis = 1;
591 }
592 }
593 }
594
595
596 /***************************************************************/
RaiseTextWindows()597 void RaiseTextWindows()
598 {
599 int i;
600
601 for (i=0; i<MAXTEXTWIN; i++) {
602 if (tinfo[i].vis) {
603 XRaiseWindow(theDisp, tinfo[i].win);
604 }
605 }
606 }
607
608
609 /***************************************************************/
SetTextCursor(c)610 void SetTextCursor(c)
611 Cursor c;
612 {
613 int i;
614
615 for (i=0; i<MAXTVWIN; i++) {
616 if (haveWindows && tinfo[i].win) XDefineCursor(theDisp, tinfo[i].win, c);
617 }
618 }
619
620
621 /***************************************************************/
KillTextWindows()622 void KillTextWindows()
623 {
624 int i;
625
626 for (i=0; i<MAXTVWIN; i++) {
627 if (haveWindows && tinfo[i].win) XDestroyWindow(theDisp, tinfo[i].win);
628 }
629 }
630
631
632 /***************************************************************/
TextCheckEvent(xev,retP,doneP)633 int TextCheckEvent(xev, retP, doneP)
634 XEvent *xev;
635 int *retP, *doneP;
636 {
637 int i;
638
639 event_retP = retP; /* so don't have to pass these all over the place */
640 event_doneP = doneP;
641
642 for (i=0; i<MAXTVWIN; i++) {
643 if (tvChkEvent(&tinfo[i], xev)) break;
644 }
645
646 if (i<MAXTVWIN) return 1;
647 return 0;
648 }
649
650
651 /***************************************************************/
TextDelWin(win)652 int TextDelWin(win)
653 Window win;
654 {
655 /* got a delete window request. see if the window is a textview window,
656 and close accordingly. Return 1 if event was eaten */
657
658 int i;
659
660 for (i=0; i<MAXTVWIN; i++) {
661 if (tinfo[i].win == win) {
662 closeText(&tinfo[i]);
663 return 1;
664 }
665 }
666
667 return 0;
668 }
669
670
671
672
673
674 /**************************************************************/
675 /*** INTERNAL FUNCTIONS ***/
676 /**************************************************************/
677
678
679
680
681
682 /***************************************************************/
closeText(tv)683 static void closeText(tv)
684 TVINFO *tv;
685 {
686 /* closes specified textview window */
687
688 int i;
689
690 XUnmapWindow(theDisp, tv->win);
691 tv->vis = 0;
692
693 for (i=0; i<MAXTEXTWIN && !tinfo[i].vis; i++);
694 if (i==MAXTEXTWIN) anyTextUp = 0;
695
696 /* free all info for this textview window */
697 if (tv->freeonclose && tv->text) free((void *)tv->text);
698 if (tv->lines) free(tv->lines);
699
700 tv->text = (const char *) NULL;
701 tv->lines = (const char **) NULL;
702 tv->numlines = tv->textlen = tv->hexmode = 0;
703
704 #ifdef TV_MULTILINGUAL
705 closeCsWin(tv);
706 #endif
707 }
708
709
710 /***************************************************************/
tvChkEvent(tv,xev)711 static int tvChkEvent(tv, xev)
712 TVINFO *tv;
713 XEvent *xev;
714 {
715 /* checks event to see if it's a text-window related thing. If it
716 is, it eats the event and returns '1', otherwise '0'. */
717
718 int rv;
719
720 rv = 1;
721
722 if (!hasBeenSized) return 0; /* ignore evrythng until we get 1st Resize */
723
724 if (xev->type == Expose) {
725 int x,y,w,h;
726 XExposeEvent *e = (XExposeEvent *) xev;
727 x = e->x; y = e->y; w = e->width; h = e->height;
728
729 /* throw away excess redraws for 'dumb' windows */
730 if (e->count > 0 && (e->window == tv->vscrl.win ||
731 e->window == tv->hscrl.win)) {}
732
733 else if (e->window == tv->vscrl.win) SCRedraw(&(tv->vscrl));
734 else if (e->window == tv->hscrl.win) SCRedraw(&(tv->hscrl));
735
736 else if (e->window == tv->win || e->window == tv->textW) { /* smart wins */
737 /* group individual expose rects into a single expose region */
738 int count;
739 Region reg;
740 XRectangle rect;
741 XEvent evt;
742
743 xvbcopy((char *) e, (char *) &evt, sizeof(XEvent));
744 reg = XCreateRegion();
745 count = 0;
746
747 do {
748 if (DEBUG) fprintf(stderr," expose: %s %d,%d %dx%d\n",
749 (e->window == tv->win) ? "tv win" : "text win",
750 rect.x, rect.y, rect.width, rect.height);
751
752 rect.x = evt.xexpose.x;
753 rect.y = evt.xexpose.y;
754 rect.width = evt.xexpose.width;
755 rect.height = evt.xexpose.height;
756 XUnionRectWithRegion(&rect, reg, reg);
757 count++;
758 } while (XCheckWindowEvent(theDisp, evt.xexpose.window,
759 ExposureMask, &evt));
760
761 XClipBox(reg, &rect); /* bounding box of region */
762 XSetRegion(theDisp, theGC, reg);
763
764 if (DEBUG) {
765 fprintf(stderr,"win = %lx, tv->win = %lx, textW = %lx\n",
766 e->window, tv->win, tv->textW);
767 fprintf(stderr,"grouped %d expose events into %d,%d %dx%d rect\n",
768 count, rect.x, rect.y, rect.width, rect.height);
769 }
770
771 if (e->window == tv->win) drawTextView(tv);
772 else if (e->window == tv->textW) drawTextW(0, &(tv->vscrl));
773
774 XSetClipMask(theDisp, theGC, None);
775 XDestroyRegion(reg);
776 }
777
778 else rv = 0;
779 }
780
781
782 else if (xev->type == ButtonPress) {
783 XButtonEvent *e = (XButtonEvent *) xev;
784 int x,y;
785 x = e->x; y = e->y;
786
787 if (e->button == Button1) {
788 if (e->window == tv->win) clickText(tv,x,y);
789 else if (e->window == tv->vscrl.win) SCTrack(&(tv->vscrl),x,y);
790 else if (e->window == tv->hscrl.win) SCTrack(&(tv->hscrl),x,y);
791 else if (e->window == tv->textW) { }
792 else rv = 0;
793 }
794 else if (e->button == Button4) { /* note min vs. max, + vs. - */
795 /* scroll regardless of where we are in the text window */
796 if (e->window == tv->win ||
797 e->window == tv->vscrl.win ||
798 e->window == tv->hscrl.win ||
799 e->window == tv->textW)
800 {
801 SCRL *sp=&(tv->vscrl);
802 int halfpage=sp->page/2;
803
804 if (sp->val > sp->min+halfpage)
805 SCSetVal(sp,sp->val-halfpage);
806 else
807 SCSetVal(sp,sp->min);
808 }
809 else rv = 0;
810 }
811 else if (e->button == Button5) { /* note max vs. min, - vs. + */
812 /* scroll regardless of where we are in the text window */
813 if (e->window == tv->win ||
814 e->window == tv->vscrl.win ||
815 e->window == tv->hscrl.win ||
816 e->window == tv->textW)
817 {
818 SCRL *sp=&(tv->vscrl);
819 int halfpage=sp->page/2;
820
821 if (sp->val < sp->max-halfpage)
822 SCSetVal(sp,sp->val+halfpage);
823 else
824 SCSetVal(sp,sp->max);
825 }
826 else rv = 0;
827 }
828 else rv = 0;
829 }
830
831
832 else if (xev->type == KeyPress) {
833 XKeyEvent *e = (XKeyEvent *) xev;
834 if (e->window == tv->win) keyText(tv, e);
835 else rv = 0;
836 }
837
838
839 else if (xev->type == ConfigureNotify) {
840 XConfigureEvent *e = (XConfigureEvent *) xev;
841
842 if (e->window == tv->win) {
843 if (DEBUG)
844 fprintf(stderr,"textview got a configure event (%dx%d)\n",
845 e->width, e->height);
846
847 if (tv->wide != e->width || tv->high != e->height) {
848 if (DEBUG) fprintf(stderr,"Forcing a redraw! (from configure)\n");
849 XClearArea(theDisp, tv->win, 0, 0,
850 (u_int) e->width, (u_int) e->height, True);
851 resizeText(tv, e->width, e->height);
852 }
853 }
854 else rv = 0;
855 }
856 else rv = 0;
857
858 return rv;
859 }
860
861
862 /***************************************************************/
resizeText(tv,w,h)863 static void resizeText(tv,w,h)
864 TVINFO *tv;
865 int w,h;
866 {
867 int i, maxw, maxh;
868 XSizeHints hints;
869
870 #ifndef TV_MULTILINGUAL
871 if (tv->wide == w && tv->high == h) return; /* no change in size */
872 #endif
873
874 if (XGetNormalHints(theDisp, tv->win, &hints)) {
875 hints.width = w;
876 hints.height = h;
877 hints.flags |= USSize;
878 XSetNormalHints(theDisp, tv->win, &hints);
879 }
880
881 tv->wide = w; tv->high = h;
882
883 /* compute maximum size of text window */
884 maxw = tv->wide - (2*LRMARGINS) - (tv->vscrl.tsize+1) - 2;
885 maxh = tv->high - (TOPMARGIN + BOTMARGIN) - (tv->hscrl.tsize+1) - 2;
886
887 tv->chwide = ((maxw - 6) / mfwide);
888 tv->chhigh = ((maxh - 6) / mfhigh);
889
890 tv->twWide = tv->chwide * mfwide + 6;
891 tv->twHigh = tv->chhigh * mfhigh + 6;
892
893 XMoveResizeWindow(theDisp, tv->textW, LRMARGINS, TOPMARGIN,
894 (u_int) tv->twWide, (u_int) tv->twHigh);
895
896 for (i=0; i<TV_E_NBUTTS; i++) {
897 tv->but[i].x = tv->wide - (TV_E_NBUTTS-i) * (BUTTW1+5);
898 tv->but[i].y = tv->high - BUTTH - 5;
899 }
900 #ifdef TV_MULTILINGUAL
901 tv->csbut.x = 5;
902 tv->csbut.y = tv->high - BUTTH - 5;
903 #endif
904
905 #ifdef TV_L10N
906 if (xlocale) {
907 for (; i<TV_J_NBUTTS; i++) {
908 tv->but[i].x = 5 + (i-TV_E_NBUTTS) * (BUTTW2+5);
909 tv->but[i].y = tv->high - BUTTH - 5;
910 }
911 }
912 #endif
913
914 computeScrlVals(tv);
915
916 tv->nopBut.x = LRMARGINS + tv->twWide + 1;
917 tv->nopBut.y = TOPMARGIN + tv->twHigh + 1;
918 }
919
920
921
922
923 /***************************************************************/
computeScrlVals(tv)924 static void computeScrlVals(tv)
925 TVINFO *tv;
926 {
927 int hmax, hpag, vmax, vpag;
928
929 if (tv->hexmode) {
930 hmax = 80 - tv->chwide;
931 vmax = tv->hexlines - tv->chhigh;
932 }
933 else { /* ASCII mode */
934 hmax = tv->maxwide - tv->chwide;
935 vmax = tv->numlines - tv->chhigh - 1;
936 }
937
938 hpag = tv->chwide / 4;
939 vpag = tv->chhigh - 1;
940
941
942 SCChange(&tv->vscrl, LRMARGINS + tv->twWide+1, TOPMARGIN,
943 1, tv->twHigh, 0, vmax, tv->vscrl.val, vpag);
944
945 SCChange(&tv->hscrl, LRMARGINS, TOPMARGIN + tv->twHigh + 1,
946 0, tv->twWide, 0, hmax, tv->hscrl.val, hpag);
947 }
948
949
950
951 /***************************************************************/
doCmd(tv,cmd)952 static void doCmd(tv, cmd)
953 TVINFO *tv;
954 int cmd;
955 {
956 switch (cmd) {
957 case TV_ASCII: doHexAsciiCmd(tv, 0); break;
958 case TV_HEX: doHexAsciiCmd(tv, 1); break;
959
960 case TV_CLOSE: if (tv == &tinfo[CMTWIN]) CloseCommentText();
961 else closeText(tv);
962 break;
963
964 #ifdef TV_L10N
965 case TV_RESCAN:
966 tv->code = selectCodeset(tv);
967 drawTextW(0, &tv->vscrl);
968 break;
969 case TV_USASCII:
970 tv->code = LOCALE_USASCII;
971 drawTextW(0, &tv->vscrl);
972 break;
973 case TV_JIS:
974 tv->code = LOCALE_JIS;
975 drawTextW(0, &tv->vscrl);
976 break;
977 case TV_EUCJ:
978 tv->code = LOCALE_EUCJ;
979 drawTextW(0, &tv->vscrl);
980 break;
981 case TV_MSCODE:
982 tv->code = LOCALE_MSCODE;
983 drawTextW(0, &tv->vscrl);
984 break;
985 #endif /* TV_L10N */
986 }
987 }
988
989
990
991 /***************************************************************/
drawTextView(tv)992 static void drawTextView(tv)
993 TVINFO *tv;
994 {
995 /* redraw the outer window */
996
997 int i, y;
998
999 if (strlen(tv->title)) { /* draw the title */
1000 y = 5;
1001
1002 XSetForeground(theDisp, theGC, infobg);
1003 XFillRectangle(theDisp, tv->win, theGC, 5+1, y+1,
1004 (u_int) StringWidth(tv->title)+6, (u_int) CHIGH+4);
1005
1006 XSetForeground(theDisp, theGC, infofg);
1007 XDrawRectangle(theDisp, tv->win, theGC, 5, y,
1008 (u_int) StringWidth(tv->title)+7, (u_int) CHIGH+5);
1009
1010 Draw3dRect(tv->win, 5+1, y+1, (u_int) StringWidth(tv->title)+5,
1011 (u_int) CHIGH+3, R3D_IN, 2, hicol, locol, infobg);
1012
1013 XSetForeground(theDisp, theGC, infofg);
1014 DrawString(tv->win, 5+3, y+ASCENT+3, tv->title);
1015 }
1016
1017 drawNumLines(tv);
1018
1019 /* draw the buttons */
1020 for (i=0; i<nbutts; i++) BTRedraw(&(tv->but[i]));
1021 #ifdef TV_MULTILINGUAL
1022 BTRedraw(&tv->csbut);
1023 #endif
1024 BTRedraw(&tv->nopBut);
1025 }
1026
1027
1028 /***************************************************************/
drawNumLines(tv)1029 static void drawNumLines(tv)
1030 TVINFO *tv;
1031 {
1032 int x, y, w, nl;
1033 char tmpstr[128];
1034
1035 if (tv->hexmode) nl = tv->hexlines;
1036 else {
1037 if (tv->numlines>0 &&
1038 tv->lines[tv->numlines-1] - tv->lines[tv->numlines-2] == 1)
1039 nl = tv->numlines - 2; /* line after last \n has zero length */
1040 else nl = tv->numlines - 1;
1041 }
1042 if (nl<0) nl = 0;
1043
1044 sprintf(tmpstr, "%d byte%s, %d line%s",
1045 tv->textlen, (tv->textlen!=1) ? "s" : "",
1046 nl, (nl!=1) ? "s" : "");
1047
1048 w = StringWidth(tmpstr) + 7; /* width of frame */
1049 x = LRMARGINS + tv->twWide + tv->vscrl.tsize+1; /* right align point */
1050 y = 6;
1051
1052 XSetForeground(theDisp, theGC, infobg);
1053 XFillRectangle(theDisp, tv->win, theGC, (x-w)+1, y+1,
1054 (u_int) (w-1), (u_int) CHIGH+4);
1055
1056 XSetForeground(theDisp, theGC, infofg);
1057 XDrawRectangle(theDisp, tv->win, theGC, x-w, y, (u_int) w, (u_int) CHIGH+5);
1058
1059 Draw3dRect(tv->win, (x-w)+1, y+1, (u_int) (w-2), (u_int) CHIGH+3,
1060 R3D_IN,2,hicol,locol,infobg);
1061
1062 XSetForeground(theDisp, theGC, infofg);
1063 DrawString(tv->win, (x-w)+3, y+ASCENT+3, tmpstr);
1064 }
1065
1066
1067 /***************************************************************/
eraseNumLines(tv)1068 static void eraseNumLines(tv)
1069 TVINFO *tv;
1070 {
1071 int x, y, w, nl;
1072 char tmpstr[64];
1073
1074 nl = (tv->hexmode) ? tv->hexlines : tv->numlines-1;
1075
1076 sprintf(tmpstr, "%d byte%s, %d line%s",
1077 tv->textlen, (tv->textlen>1) ? "s" : "",
1078 nl, (nl>1) ? "s" : "");
1079
1080 w = StringWidth(tmpstr) + 7; /* width of frame */
1081 x = LRMARGINS + tv->twWide + tv->vscrl.tsize+1; /* right align point */
1082 y = 5;
1083
1084 XClearArea(theDisp, tv->win, x-w, y, (u_int) w+1, (u_int) CHIGH+7, False);
1085 }
1086
1087
1088 /***************************************************************/
drawTextW(delta,sptr)1089 static void drawTextW(delta, sptr)
1090 int delta;
1091 SCRL *sptr;
1092 {
1093 int i, j, lnum, hpos, vpos, cpos, lwide;
1094 #ifndef TV_MULTILINGUAL
1095 int extrach;
1096 #endif
1097 #ifdef TV_L10N
1098 int desig_stat; /* for ISO 2022-JP */
1099 /* 0: ASCII, 1: JIS X 0208, 2: GL is JIS X 0201 kana */
1100 #endif
1101 TVINFO *tv;
1102 char linestr[512];
1103 byte *lp;
1104 const byte *sp, *ep;
1105
1106 /* figure out TVINFO pointer from SCRL pointer */
1107 for (i=0; i<MAXTVWIN && sptr != &tinfo[i].vscrl
1108 && sptr != &tinfo[i].hscrl; i++);
1109 if (i==MAXTVWIN) return; /* didn't find one */
1110
1111 tv = &tinfo[i];
1112
1113 /* make sure we've been sized. Necessary, as creating/modifying the
1114 scrollbar calls this routine directly, rather than through
1115 TextCheckEvent() */
1116
1117 if (!hasBeenSized) return;
1118
1119 XSetForeground(theDisp, theGC, infofg);
1120 XSetBackground(theDisp, theGC, infobg);
1121 XSetFont(theDisp, theGC, monofont);
1122
1123 hpos = tv->hscrl.val;
1124 vpos = tv->vscrl.val;
1125 lwide = (tv->chwide < 500) ? tv->chwide : 500;
1126
1127 /* draw text */
1128 if (!tv->hexmode) { /* ASCII mode */
1129 #ifdef TV_MULTILINGUAL
1130 XClearArea(theDisp, tv->textW, 0, 0,
1131 (u_int) tv->twWide, (u_int) tv->twHigh, False);
1132 if(tv->txt == NULL)
1133 return;
1134 else {
1135 int i;
1136 int y;
1137 struct ml_text *tp = tv->txt;
1138 struct ml_line *lp2;
1139
1140 XSetFunction(theDisp, theGC, GXcopy);
1141 XSetClipMask(theDisp, theGC, None);
1142 y = 3;
1143 for (lp2 = &tp->lines[vpos], i = tp->nlines - vpos;
1144 i > 0; lp2++, i--) {
1145 XDrawText16(theDisp, tv->textW, theGC,
1146 -mfwide * hpos + 3, y + lp2->ascent,
1147 lp2->items, lp2->nitems);
1148 y += lp2->ascent + lp2->descent;
1149 if (y > tv->twHigh)
1150 break;
1151 }
1152 }
1153 #else
1154 for (i=0; i<tv->chhigh; i++) { /* draw each line */
1155 lnum = i + vpos;
1156 if (lnum < tv->numlines-1) {
1157
1158 /* find start of displayed portion of line. This is *wildly*
1159 complicated by the ctrl-character and tab expansion... */
1160
1161 sp = (byte *) tv->lines[lnum];
1162 ep = (byte *) tv->lines[lnum+1] - 1; /* ptr to last disp ch in line */
1163
1164 extrach = 0;
1165
1166 for (cpos=0; cpos<hpos && sp<ep; cpos++) {
1167 if (!extrach) {
1168 if (*sp == '\011') { /* tab to next multiple of 8 */
1169 extrach = ((cpos+8) & (~7)) - cpos;
1170 extrach--;
1171 }
1172 else if (*sp == '\015') { /* ^M not displayed */
1173 cpos--; sp++;
1174 }
1175 else if (*sp < 32) extrach = 1;
1176
1177 #ifdef TV_L10N
1178 else if (!tv->code && *sp > 127) extrach = 3;
1179 #else
1180 else if (*sp > 127) extrach = 3;
1181 #endif
1182
1183 else sp++;
1184 }
1185 else {
1186 extrach--;
1187 if (!extrach) sp++;
1188 }
1189 }
1190
1191 /* at this point, 'sp' is pointing to the first char to display.
1192 if sp is a 'special' character, extrach is the # of chars
1193 left to display of the 'expanded' version. If sp>=ep, a blank
1194 line should be printed */
1195
1196 /* build up the linestr buffer, which is the current line, padded
1197 with blanks to a width of exactly tv->chwide chars */
1198 #ifdef TV_L10N
1199 desig_stat = 0; /* for ISO 2022-JP */
1200 /* 0: ASCII, 1: JIS X 0208, 2: GL is JIS X 0201 kana */
1201 #endif
1202 for (cpos=0, lp=(byte *) linestr; cpos<lwide; cpos++, lp++) {
1203 if (sp>=ep) *lp = ' ';
1204 else {
1205 if (*sp == '\011') { /* tab to next multiple of 8 */
1206 if (!extrach) extrach = ((cpos+hpos+8) & (~7)) - (cpos+hpos);
1207
1208 if (extrach) *lp = ' ';
1209 }
1210
1211 else if (*sp == '\015') { /* don't show ^M */
1212 cpos--; lp--; sp++;
1213 }
1214
1215 #ifdef TV_L10N
1216 else if (*sp < 32 && !(tv->code == LOCALE_JIS && *sp == 0x1b)) {
1217 #else
1218 else if (*sp < 32) {
1219 #endif
1220 if (!extrach) extrach = 2;
1221 if (extrach == 2) *lp = '^';
1222 else if (extrach == 1) *lp = *sp + 64;
1223 }
1224
1225 #ifdef TV_L10N
1226 /* convert to EUC-Japan */
1227 else if (tv->code == LOCALE_JIS) {
1228 if (*sp == 0x1b) { /* ESC */
1229 if (*(sp+1) == '$') {
1230 if (*(sp+2) == 'B' || *(sp+2) == 'A' || *(sp+2) == '@') {
1231 /* ESC $ B, ESC $ A, ESC $ @ */
1232 desig_stat = 1;
1233 sp += 3; cpos--; lp--;
1234 }
1235 else if (*(sp+2) == '(' && *(sp+3) == 'B') {
1236 /* ESC $ ( B */
1237 desig_stat = 1;
1238 sp += 4; cpos--; lp--;
1239 }
1240 }
1241 else if (*(sp+1) == '(') {
1242 if (*(sp+2) == 'B' || *(sp+2) == 'J' || *(sp+2) == 'H') {
1243 /* ESC ( B, ESC ( J, ESC ( H */
1244 desig_stat = 0;
1245 sp += 3; cpos--; lp--;
1246 }
1247 else if (*(sp+2) == 'I') {
1248 /* ESC ( I */
1249 desig_stat = 2;
1250 sp += 3; cpos--; lp--;
1251 }
1252 }
1253 else if (*(sp+1) == ')' && *(sp+2) == 'I') {
1254 /* ESC ) I */
1255 desig_stat = 2;
1256 sp += 3; cpos--; lp--;
1257 }
1258 else { /* error */
1259 *lp = ' '; sp++;
1260 }
1261 }
1262
1263 else {
1264 switch (desig_stat) {
1265 case 0: /* ASCII */
1266 *lp = *sp++;
1267 break;
1268 case 1: /* JIS X 0208 */
1269 *lp++ = *sp++ | 0x80;
1270 *lp = *sp++ | 0x80;
1271 cpos++;
1272 break;
1273 case 2: /* JIS X 0201 kana */
1274 #if defined(__osf__) && !defined(X_LOCALE)
1275 *lp = '='; sp++;
1276 #else
1277 *lp++ = 0x8e; /* ^N | 0x80 */
1278 *lp = *sp++ | 0x80;
1279 #endif
1280 break;
1281 default: /* error */
1282 *lp = *sp++;
1283 break;
1284 }
1285 }
1286 }
1287
1288 else if (tv->code == LOCALE_MSCODE) {
1289 if ((*sp >= 0x81 && *sp <= 0x9f)
1290 || (*sp >= 0xe0 && *sp <= 0xef)) {
1291 static u_char c1, c2;
1292
1293 /*fprintf(stderr, "(%x,%x)->", *sp, *(sp+1));*/
1294 c1 = ((*sp - ((*sp>=0xe0) ? 0xb0 : 0x70)) << 1)
1295 - ((*(sp+1)<=0x9e) ? 1 : 0);
1296 c2 = *(sp+1);
1297 if (c2 >= 0x9f) c2 -= 0x7e; /* 0x9F - 0xFC */
1298 else if (c2 >= 0x80) c2 -= 0x20; /* 0x80 - 0x9E */
1299 else c2 -= 0x1f; /* 0x40 - 0x7E */
1300
1301 *lp++ = c1 | 0x80;
1302 *lp = c2 | 0x80;
1303 sp += 2;
1304 /*fprintf(stderr, "(%x %x) ", c1 | 0x80, c2 | 0x80);*/
1305 cpos++;
1306 }
1307
1308 else if (*sp >= 0xa1 && *sp <= 0xdf) { /* JIS X 0201 kana */
1309 #if defined(__osf__) && !defined(X_LOCALE)
1310 *lp = '='; sp++;
1311 #else
1312 *lp++ = 0x8e; /* ^N | 0x80 */
1313 *lp = *sp++;
1314 #endif
1315 }
1316
1317 else *lp = *sp++;
1318 }
1319 #endif /* TV_L10N */
1320
1321 #ifdef TV_L10N
1322 else if (!tv->code && *sp > 127) {
1323 #else
1324 else if (*sp > 127) {
1325 #endif
1326 if (!extrach) extrach = 4;
1327 if (extrach == 4) *lp = '\\';
1328 else if (extrach == 3) *lp = ((u_char)(*sp & 0700) >> 6) + '0';
1329 else if (extrach == 2) *lp = ((u_char)(*sp & 0070) >> 3) + '0';
1330 else if (extrach == 1) *lp = ((*sp & 0007)) + '0';
1331 }
1332
1333 else *lp = *sp++;
1334
1335 if (extrach) {
1336 extrach--;
1337 if (!extrach) sp++;
1338 }
1339 }
1340 }
1341 #ifdef TV_L10N
1342 *lp = '\0'; /* terminate linestr */
1343 #endif
1344 }
1345
1346 else { /* below bottom of file. Just build a blank str */
1347 for (cpos = 0; cpos<lwide; cpos++) linestr[cpos]=' ';
1348 }
1349
1350 /* draw the line */
1351 #ifdef TV_L10N
1352 if (xlocale)
1353 XmbDrawImageString(theDisp, tv->textW, monofset, theGC,
1354 3, i*mfhigh + 1 + mfascent, linestr, strlen(linestr));
1355 else
1356 #endif
1357 XDrawImageString(theDisp, tv->textW, theGC,
1358 3, i*mfhigh + 3 + mfascent, linestr, lwide);
1359 } /* for i ... */
1360 #endif /* TV_MULTILINGUAL */
1361 } /* if hexmode */
1362
1363
1364 else { /* HEX MODE */
1365 for (i=0; i<tv->chhigh; i++) { /* draw each line */
1366 lnum = i + vpos;
1367 if (lnum < tv->hexlines) {
1368
1369 char hexstr[80], tmpstr[16];
1370
1371 /* generate hex for this line */
1372 sprintf(hexstr, "0x%08x: ", lnum * 0x10);
1373
1374 sp = (const byte *) tv->text + lnum * 0x10;
1375 ep = (const byte *) tv->text + tv->textlen; /* ptr to end of buffer */
1376
1377 for (j=0; j<16; j++) {
1378 if (sp+j < ep) sprintf(tmpstr,"%02x ", sp[j]);
1379 else sprintf(tmpstr," ");
1380 strcat(hexstr, tmpstr);
1381
1382 if (j==7) {
1383 if (sp+8<ep) strcat(hexstr,"- ");
1384 else strcat(hexstr," ");
1385 }
1386 }
1387 strcat(hexstr," ");
1388 lp = (byte *) hexstr + strlen(hexstr);
1389
1390 for (j=0; j<16; j++) {
1391 if (sp+j < ep) {
1392 #ifdef TV_L10N
1393 if (sp[j] >= 32 && (sp[j] <= 127 || tv->code)) *lp++ = sp[j];
1394 #else
1395 if (sp[j] >= 32 && sp[j] <= 127) *lp++ = sp[j];
1396 #endif
1397 else *lp++ = '.';
1398 }
1399 else *lp++ = ' ';
1400 }
1401 *lp = '\0';
1402
1403
1404 /* at this point, 'hexstr' contains an 80 column hex thingy.
1405 now build 'linestr', which is going to have hexstr shifted
1406 and/or padded with blanks (ie, the displayed portion or hexstr) */
1407
1408 /* skip obscured beginning of line, if any */
1409 for (cpos=0, sp=(byte *) hexstr; cpos<hpos && *sp; cpos++, sp++);
1410
1411 for (cpos=0, lp=(byte *)linestr; cpos<lwide; cpos++, lp++) {
1412 if (*sp) { *lp = *sp++; }
1413 else *lp = ' ';
1414 }
1415 }
1416 else { /* below bottom of file. just build blank str */
1417 for (cpos=0; cpos<lwide; cpos++) linestr[cpos]=' ';
1418 }
1419
1420 /* draw the line */
1421 XDrawImageString(theDisp, tv->textW, theGC,
1422 3, i*mfhigh + 3 + mfascent, linestr, lwide);
1423 } /* for i ... */
1424 } /* else hexmode */
1425
1426
1427
1428 XSetFont(theDisp, theGC, mfont);
1429
1430 Draw3dRect(tv->textW, 0, 0, (u_int) (tv->twWide-1), (u_int) (tv->twHigh-1),
1431 R3D_IN, 2, hicol, locol, infobg);
1432 }
1433
1434
1435
1436 /***************************************************************/
clickText(tv,x,y)1437 static void clickText(tv, x,y)
1438 TVINFO *tv;
1439 int x,y;
1440 {
1441 int i;
1442 BUTT *bp;
1443
1444 for (i=0, bp=tv->but; i<nbutts; i++, bp++) {
1445 if (PTINRECT(x,y,bp->x,bp->y,bp->w,bp->h)) break;
1446 }
1447
1448 if (i<nbutts) {
1449 if (BTTrack(bp)) doCmd(tv, i);
1450 return;
1451 }
1452
1453 #ifdef TV_MULTILINGUAL
1454 if (PTINRECT(x, y, tv->csbut.x, tv->csbut.y, tv->csbut.w, tv->csbut.h)) {
1455 if (BTTrack(&tv->csbut))
1456 openCsWin(tv);
1457 }
1458 #endif
1459 }
1460
1461
1462
1463
1464 /***************************************************************/
keyText(tv,kevt)1465 static void keyText(tv, kevt)
1466 TVINFO *tv;
1467 XKeyEvent *kevt;
1468 {
1469 char buf[128];
1470 KeySym ks;
1471 int stlen, shift, dealt, ck;
1472
1473 stlen = XLookupString(kevt, buf, 128, &ks, (XComposeStatus *) NULL);
1474 shift = kevt->state & ShiftMask;
1475 ck = CursorKey(ks, shift, 1);
1476 dealt = 1;
1477
1478 RemapKeyCheck(ks, buf, &stlen);
1479
1480 /* check for arrow keys, Home, End, PgUp, PgDown, etc. */
1481 if (ck!=CK_NONE) textKey(tv,ck);
1482 else dealt = 0;
1483
1484 if (dealt || !stlen) return;
1485
1486 /* keyboard equivalents */
1487 switch (buf[0]) {
1488 case '\001': case 'a': case 'A':
1489 doCmd(tv, TV_ASCII); break; /* ^A = Ascii */
1490 case '\010': case 'h': case 'H':
1491 doCmd(tv, TV_HEX); break; /* ^H = Hex */
1492
1493 case '\021': case 'q': case 'Q':
1494 case '\003': case 'c': case 'C':
1495 case '\033':
1496 doCmd(tv, TV_CLOSE); break; /* ESC = Close window */
1497
1498 default: break;
1499 }
1500
1501 #ifdef TV_L10N
1502 if (xlocale) {
1503 switch (buf[0]) {
1504 case '\022': case 'r': case 'R':
1505 doCmd(tv, TV_RESCAN); break;
1506 case '\012': case 'j': case 'J':
1507 doCmd(tv, TV_JIS); break;
1508 case '\005': case 'e': case 'E':
1509 case '\025': case 'u': case 'U':
1510 doCmd(tv, TV_EUCJ); break;
1511 case '\015': case 'm': case 'M':
1512 case '\023': case 's': case 'S':
1513 doCmd(tv, TV_MSCODE); break;
1514
1515 default: break;
1516 }
1517 }
1518 #endif /* TV_L10N */
1519
1520 }
1521
1522
1523 /***************************************************/
textKey(tv,key)1524 static void textKey(tv, key)
1525 TVINFO *tv;
1526 int key;
1527 {
1528 if (!tv->textlen) return;
1529
1530 /* an arrow key (or something like that) was pressed in icon window.
1531 change selection/scrollbar accordingly */
1532
1533 if (key == CK_UP) SCSetVal(&tv->vscrl, tv->vscrl.val - 1);
1534 if (key == CK_DOWN) SCSetVal(&tv->vscrl, tv->vscrl.val + 1);
1535
1536 if (key == CK_LEFT) SCSetVal(&tv->hscrl, tv->hscrl.val - 1);
1537 if (key == CK_RIGHT) SCSetVal(&tv->hscrl, tv->hscrl.val + 1);
1538
1539 if (key == CK_PAGEUP) SCSetVal(&tv->vscrl, tv->vscrl.val - tv->vscrl.page);
1540 if (key == CK_PAGEDOWN) SCSetVal(&tv->vscrl, tv->vscrl.val + tv->vscrl.page);
1541 if (key == CK_HOME) SCSetVal(&tv->vscrl, tv->vscrl.min);
1542 if (key == CK_END) SCSetVal(&tv->vscrl, tv->vscrl.max);
1543 }
1544
1545
1546 /***************************************************/
doHexAsciiCmd(tv,hexval)1547 static void doHexAsciiCmd(tv, hexval)
1548 TVINFO *tv;
1549 int hexval;
1550 {
1551 int i, oldvscrl, pos;
1552
1553 if (hexval == tv->hexmode) return; /* already ascii */
1554 eraseNumLines(tv);
1555 tv->hexmode = hexval;
1556 drawNumLines(tv);
1557
1558 oldvscrl = tv->vscrl.val;
1559
1560 /* compute vals, as width and length of text has changed */
1561 computeScrlVals(tv);
1562
1563 /* try to show same area of file */
1564 if (hexval) { /* switched to hex mode */
1565 if (oldvscrl < tv->numlines-1) {
1566 pos = tv->lines[oldvscrl] - tv->text;
1567
1568 SCSetVal(&tv->vscrl, pos / 16);
1569 }
1570 }
1571 else { /* switch to ascii mode */
1572 pos = oldvscrl * 16;
1573 for (i=0; i<tv->numlines-1; i++) {
1574 if (tv->lines[i+1] - tv->text > pos &&
1575 tv->lines[i] - tv->text <= pos) break;
1576 }
1577 if (i<tv->numlines-1) SCSetVal(&tv->vscrl, i);
1578 }
1579
1580 #ifdef TV_L10N
1581 /* redraw text */
1582 if (xlocale) {
1583 XClearArea(theDisp, tv->textW, 0, 0,
1584 (u_int) tv->twWide, (u_int) tv->twHigh, False);
1585
1586 drawTextW(0, &tv->vscrl);
1587 }
1588 #endif
1589 #ifdef TV_MULTILINGUAL
1590 XClearArea(theDisp, tv->textW, 0, 0,
1591 (u_int) tv->twWide, (u_int) tv->twHigh, False);
1592 drawTextW(0, &tv->vscrl);
1593 #endif
1594 }
1595
1596
1597 /***************************************************/
computeText(tv)1598 static void computeText(tv)
1599 TVINFO *tv;
1600 {
1601 /* compute # of lines and linestarts array for given text */
1602
1603 int i,j,wide,maxwide,space;
1604 const byte *sp;
1605
1606 #ifdef TV_L10N
1607 /* select code-set */
1608 if (xlocale)
1609 tv->code = selectCodeset(tv);
1610 #endif /* TV_L10N */
1611
1612 if (!tv->text) {
1613 tv->numlines = tv->hexlines = 0;
1614 tv->lines = (const char **) NULL;
1615 #ifdef TV_MULTILINGUAL
1616 if (tv->cv_text != NULL) {
1617 free(tv->cv_text);
1618 tv->cv_text = NULL;
1619 }
1620 tv->txt = NULL;
1621 #endif
1622 return;
1623 }
1624
1625 /* count the # of newline characters in text */
1626 for (i=0, sp=(const byte *) tv->text, tv->numlines=0; i<tv->textlen; i++, sp++) {
1627 if (*sp == '\n') tv->numlines++;
1628 }
1629
1630 /* +1 for start of line after last \n char, +1 to mark end of that line */
1631 tv->numlines += 2;
1632
1633 /* build lines array */
1634 tv->lines = (const char **) malloc(tv->numlines * sizeof(char *));
1635 if (!tv->lines) FatalError("out of memory in computeText()");
1636
1637 j = 0;
1638 tv->lines[j++] = tv->text;
1639 for (i=0, sp=(const byte *) tv->text; i<tv->textlen; i++, sp++) {
1640 if (*sp == '\n') tv->lines[j++] = (char *) (sp + 1);
1641 }
1642
1643 tv->lines[tv->numlines - 1] = tv->text + tv->textlen + 1;
1644
1645 /* each line has a trailing '\n' character, except for the last line,
1646 which has a trailing '\0' character. In any case, all lines can
1647 be printed by printing ((lines[n+1] - lines[n]) - 1) characters,
1648 starting with lines[n].
1649
1650 Note that there is one more lines[] entry than the actual # of lines,
1651 so as to mark the end of the last line in the same way as all the
1652 others */
1653
1654 /* compute length of longest line, when shown in 'ascii' mode. Takes
1655 into account the fact that non-printing chars (<32 or >127) will be
1656 shown in an 'expanded' form. (<32 chars will be shown as '^A'
1657 (or whatever), and >127 chars will be shown as octal '\275') */
1658
1659 maxwide = 0;
1660 for (i=0; i<tv->numlines-1; i++) {
1661 /* compute displayed width of line #i */
1662 for (sp=(const byte *) tv->lines[i], wide=0; sp<(const byte *) tv->lines[i+1]-1;
1663 sp++) {
1664 if (*sp == '\011') { /* tab to next multiple of 8 */
1665 space = ((wide+8) & (~7)) - wide;
1666 wide += space;
1667 }
1668 else if (*sp < 32) wide += 2;
1669 #ifdef TV_L10N
1670 else if (*sp > 127 && !tv->code) wide += 4;
1671 #else
1672 else if (*sp > 127) wide += 4;
1673 #endif
1674 else wide++;
1675 }
1676 if (wide > maxwide) maxwide = wide;
1677 }
1678 tv->maxwide = maxwide;
1679
1680 #ifdef TV_MULTILINGUAL
1681 ml_set_charsets(tv->ctx, &tv->ccs.coding_system);
1682 if (tv->cv_text != NULL) {
1683 free(tv->cv_text);
1684 tv->cv_text = NULL;
1685 }
1686 if (tv->ccs.converter == NULL) {
1687 tv->txt = ml_draw_text(tv->ctx, tv->text, tv->textlen);
1688 } else {
1689 tv->cv_text = (*tv->ccs.converter)(tv->text, tv->textlen, &tv->cv_len);
1690 tv->txt = ml_draw_text(tv->ctx, tv->cv_text, tv->cv_len);
1691 }
1692 tv->maxwide = tv->txt->width / mfwide;
1693 tv->numlines = tv->txt->height / mfhigh + 1;
1694 #endif
1695
1696 tv->hexlines = (tv->textlen + 15) / 16;
1697 }
1698
1699
1700 /***************************************************/
1701 #ifdef TV_L10N
selectCodeset(tv)1702 static int selectCodeset(tv)
1703 TVINFO *tv;
1704 {
1705 const byte *sp;
1706 int i, len;
1707 int code = LOCALE_USASCII; /* == 0 */
1708
1709
1710 len = tv->textlen;
1711
1712 /* select code-set */
1713 if (xlocale) {
1714 sp = (const byte *) tv->text; i = 0;
1715 while (i < len - 1) {
1716 if (*sp == 0x1b &&
1717 (*(sp+1) == '$' || *(sp+1) == '(' || *(sp+1) == ')')) {
1718 code = LOCALE_JIS;
1719 break;
1720 }
1721
1722 else if (*sp >= 0xa1 && *sp <= 0xdf) {
1723 if (*(sp+1) >= 0xf0 && *(sp+1) <= 0xfe) {
1724 code = LOCALE_EUCJ;
1725 break;
1726 }
1727 # if (LOCALE_DEFAULT == LOCALE_EUCJ)
1728 else {
1729 sp++; i++;
1730 }
1731 # endif
1732 }
1733
1734 else if ((*sp >= 0x81 && *sp <= 0x9f) || (*sp >= 0xe0 && *sp <= 0xef)) {
1735 if ((*(sp+1) >= 0x40 && *(sp+1) <= 0x7e) || *(sp+1) == 0x80) {
1736 code = LOCALE_MSCODE;
1737 break;
1738 }
1739 else if (*(sp+1) == 0xfd || *(sp+1) == 0xfe) {
1740 code = LOCALE_EUCJ;
1741 break;
1742 }
1743 else {
1744 sp++; i++;
1745 }
1746 }
1747
1748 else if (*sp >= 0xf0 && *sp <= 0xfe) {
1749 code = LOCALE_EUCJ;
1750 break;
1751 }
1752
1753 sp++; i++;
1754 }
1755 if (!code) code = LOCALE_DEFAULT;
1756 }
1757
1758 return code;
1759 }
1760 #endif /* TV_L10N */
1761
1762 #ifdef TV_MULTILINGUAL
setCodingSpec(tv,cs)1763 static void setCodingSpec(tv, cs)
1764 TVINFO *tv;
1765 struct coding_spec *cs;
1766 {
1767 if (xvbcmp((char *) &tv->ccs, (char *) cs, sizeof *cs) == 0)
1768 return;
1769
1770 tv->ccs = *cs;
1771 #if 0
1772 ml_set_charsets(tv->ctx, &tv->ccs.coding_system);
1773 if (tv->cv_text != NULL) {
1774 free(tv->cv_text);
1775 tv->cv_text = NULL;
1776 }
1777 if (tv->ccs.converter == NULL) {
1778 tv->txt = ml_draw_text(tv->ctx, tv->text, tv->textlen);
1779 } else {
1780 tv->cv_text = (*tv->ccs.converter)(tv->text, tv->textlen, &tv->cv_len);
1781 tv->txt = ml_draw_text(tv->ctx, tv->cv_text, tv->cv_len);
1782 }
1783 #else
1784 computeText(tv);
1785 computeScrlVals(tv);
1786 #endif
1787 /* drawTextW(0, &tv->vscrl); */
1788 }
1789 #endif
1790
1791
1792 /**********************************************************************/
1793 /* BUILT-IN TEXT FILES ************************************************/
1794 /**********************************************************************/
1795
1796
1797
1798 static char license[10240];
1799
1800 /***************************************************************/
ShowLicense()1801 void ShowLicense()
1802 {
1803 license[0] = '\0';
1804
1805 /* build the license text */
1806 #ifdef LC
1807 # undef LC
1808 #endif
1809 #ifdef __STDC__ /* since "x" is always a static string, this works: */
1810 # define LC(x) (strcat(license, x "\n"))
1811 #else
1812 # define LC(x) (strcat(license, x), strcat(license, "\n"))
1813 #endif
1814
1815 LC("(Note: This has been changed, and hopefully clarified, from the 3.00");
1816 LC("version of this info. Please read it.)");
1817 LC("");
1818 LC("Thank you for acquiring a copy of XV, a pretty nifty X program.");
1819 LC("I hope you enjoy using it, as I've enjoyed writing it.");
1820 LC("");
1821 LC("The latest version of XV (or at least a pointer to it) is available");
1822 LC("via anonymous ftp on ftp.cis.upenn.edu, in the directory pub/xv. If");
1823 LC("you're not sure if you have the latest version, or you are missing the");
1824 LC("source or documentation for XV, PLEASE pick up the latest version of");
1825 LC("the xv distribution. Do *not* send mail unless absolutely necessary");
1826 LC("(ie, you don't have ftp capability).");
1827 LC("");
1828 LC("Note: The documentation (README.jumbo, xvdocs.ps, and/or xvdocs.pdf)");
1829 #ifdef __STDC__
1830 LC("may be installed in '" DOCDIR "'.");
1831 #else
1832 LC("may be installed in '/usr/local/share/doc/xv'.");
1833 #endif
1834 LC("");
1835 LC("If you're viewing this information via the 'About XV' command, and");
1836 LC("you'd like to print it out, a copy of this info can be found in the ");
1837 LC("README file in the top-level XV source directory. Print that. If you");
1838 LC("don't have it, see the previous paragraph.");
1839 LC("");
1840 LC("");
1841 LC("XV Licensing Information");
1842 LC("------------------------");
1843 LC("XV IS SHAREWARE FOR PERSONAL USE ONLY.");
1844 LC("");
1845 LC("You may use XV for your own amusement, and if you find it nifty,");
1846 LC("useful, generally cool, or of some value to you, your registration fee");
1847 LC("would be greatly appreciated. $25 is the standard registration fee,");
1848 LC("though of course, larger amounts are quite welcome. Folks who donate");
1849 LC("$40 or more can receive a printed, bound copy of the XV manual for no");
1850 LC("extra charge. If you want one, just ask. Be sure to specify the");
1851 LC("version of xv that you are using!");
1852 LC("");
1853 LC("COMMERCIAL, GOVERNMENT, AND INSTITUTIONAL USERS MUST REGISTER THEIR");
1854 LC("COPIES OF XV.");
1855 LC("");
1856 LC("This does *not* mean that you are required to register XV just because");
1857 LC("you play with it on the workstation in your office. This falls under");
1858 LC("the heading of 'personal use'. If you are a sysadmin, you can put XV");
1859 LC("up in a public directory for your users amusement. Again, 'personal");
1860 LC("use', albeit plural.");
1861 LC("");
1862 LC("On the other hand, if you use XV in the course of doing your work,");
1863 LC("whatever your 'work' may happen to be, you *must* register your");
1864 LC("copy of XV. (Note: If you are a student, and you use XV to do");
1865 LC("classwork or research, you should get your professor/teacher/advisor");
1866 LC("to purchase an appropriate number of copies.)");
1867 LC("");
1868 LC("XV licenses are $25 each. You should purchase one license per");
1869 LC("workstation, or one per XV user, whichever is the smaller number. XV");
1870 LC("is *not* sold on a 'number of concurrent users' basis. If XV was some");
1871 LC("$1000 program, yes, that would be a reasonable request, but at $25,");
1872 LC("it's not. Also, given that XV is completely unlocked, there is no way");
1873 LC("to enforce any 'number of concurrent users' limits, so it isn't sold");
1874 LC("that way.");
1875 LC("");
1876 LC("Printed and bound copies of the 100-odd page XV manual are available");
1877 LC("for $15 each. Note that manuals are *only* sold with, at minimum, an");
1878 LC("equal number of licenses. (e.g. if you purchase 5 licenses, you can");
1879 LC("also purchase *up to* 5 copies of the manual)");
1880 LC("");
1881 LC("The source code to the program can be had (as a compressed 'tar' file");
1882 LC("split over a couple 3.5\" MS-DOS formatted disks) for $15, for those");
1883 LC("who don't have ftp capabilities.");
1884 LC("");
1885 LC("Orders outside the US and Canada must add an additional $5 per manual");
1886 LC("ordered to cover the additional shipping charges.");
1887 LC("");
1888 LC("Checks, money orders, and purchase orders are accepted. Credit cards");
1889 LC("are not. All forms of payment must be payable in US Funds. Checks");
1890 LC("must be payable through a US bank (or a US branch of a non-US bank).");
1891 LC("Purchase orders for less than $50, while still accepted, are not");
1892 LC("encouraged.");
1893 LC("");
1894 LC("All payments should be payable to 'John Bradley', and mailed to:");
1895 LC(" John Bradley");
1896 LC(" 1053 Floyd Terrace");
1897 LC(" Bryn Mawr, PA 19010");
1898 LC(" USA");
1899 LC("");
1900 LC("");
1901 LC("Site Licenses");
1902 LC("-------------");
1903 LC("If you are planning to purchase 10 or more licenses, site licenses are");
1904 LC("available, at a substantial discount. Site licenses let you run XV on");
1905 LC("any and all computing equipment at the site, for any purpose");
1906 LC("whatsoever. The site license covers the current version of XV, and");
1907 LC("any versions released within one year of the licensing date. You are");
1908 LC("also allowed to duplicate and distribute an unlimited number of copies");
1909 LC("of the XV manual, but only for use within the site. Covered versions");
1910 LC("of the software may be run in perpetuity.");
1911 LC("");
1912 LC("Also, it should be noted that a 'site' can be defined as anything");
1913 LC("you'd like. It can be a physical location (a room, building,");
1914 LC("location, etc.), an organizational grouping (a workgroup, department,");
1915 LC("division, etc.) or any other logical grouping (\"the seventeen");
1916 LC("technical writers scattered about our company\", etc.).");
1917 LC("");
1918 LC("The site license cost will be based on your estimate of the number of");
1919 LC("XV users or workstations at your site, whichever is the smaller");
1920 LC("number.");
1921 LC("");
1922 LC("If you are interested in obtaining a site license, please contact the");
1923 LC("author via electronic mail or FAX (see below for details). Send");
1924 LC("information regarding your site (the name or definition of the 'site',");
1925 LC("a physical address, a fax number, and an estimate of the number of");
1926 LC("users or workstations), and we'll get a site license out to you for");
1927 LC("your examination.");
1928 LC("");
1929 LC("");
1930 LC("Copyright Notice");
1931 LC("----------------");
1932 LC("XV is Copyright 1989, 1994 by John Bradley");
1933 LC("");
1934 LC("Permission to copy and distribute XV in its entirety, for");
1935 LC("non-commercial purposes, is hereby granted without fee, provided that");
1936 LC("this license information and copyright notice appear in all copies.");
1937 LC("");
1938 LC("If you redistribute XV, the *entire* contents of this distribution");
1939 LC("must be distributed, including the README, and INSTALL files, the");
1940 LC("sources, and the complete contents of the 'docs' directory.");
1941 LC("");
1942 LC("Note that distributing XV 'bundled' in with any product is considered");
1943 LC("to be a 'commercial purpose'.");
1944 LC("");
1945 LC("Also note that any copies of XV that are distributed MUST be built");
1946 LC("and/or configured to be in their 'unregistered copy' mode, so that it");
1947 LC("is made obvious to the user that XV is shareware, and that they should");
1948 LC("consider registering, or at least reading this information.");
1949 LC("");
1950 LC("The software may be modified for your own purposes, but modified");
1951 LC("versions may not be distributed without prior consent of the author.");
1952 LC("");
1953 LC("This software is provided 'as-is', without any express or implied");
1954 LC("warranty. In no event will the author be held liable for any damages");
1955 LC("arising from the use of this software.");
1956 LC("");
1957 LC("If you would like to do something with XV that this copyright");
1958 LC("prohibits (such as distributing it with a commercial product, using");
1959 LC("portions of the source in some other program, distributing registered");
1960 LC("copies, etc.), please contact the author (preferably via email).");
1961 LC("Arrangements can probably be worked out.");
1962 LC("");
1963 LC("");
1964 LC("The author may be contacted via:");
1965 LC(" US Mail: John Bradley");
1966 LC(" 1053 Floyd Terrace");
1967 LC(" Bryn Mawr, PA 19010");
1968 LC("");
1969 LC(" FAX: (610) 520-2042");
1970 LC("");
1971 LC("Electronic Mail regarding XV should be sent to one of these addresses:");
1972 LC(" xv@devo.dccs.upenn.edu - general XV questions");
1973 LC(" xvbiz@devo.dccs.upenn.edu - all XV licensing questions");
1974 LC(" xvtech@devo.dccs.upenn.edu - bug reports, technical questions");
1975 LC("");
1976 LC("Please do *not* send electronic mail directly to the author, as he");
1977 LC("gets more than enough as it is.");
1978 LC("");
1979
1980 #undef LC
1981
1982 OpenTextView(license, (int) strlen(license), "About XV", 0);
1983 }
1984
1985
1986
1987 static char keyhelp[10240];
1988
1989 /***************************************************************/
ShowKeyHelp()1990 void ShowKeyHelp()
1991 {
1992 keyhelp[0] = '\0';
1993
1994 #undef LC
1995 #ifdef __STDC__ /* since "x" is always a static string, this works: */
1996 # define LC(x) (strcat(keyhelp, x "\n"))
1997 #else
1998 # define LC(x) (strcat(keyhelp, x), strcat(keyhelp, "\n"))
1999 #endif
2000
2001 LC("XV Mouse and Keyboard Usage");
2002 LC("===========================");
2003 LC("");
2004 LC("Part 1: Mouse Usage in the Image Window");
2005 LC("----------------------------------------");
2006 LC(" Button1 - draws a selection rectangle");
2007 LC(" Button2 - pixel values, measures dist., picks color");
2008 LC(" Button3 - opens/closes the 'xv controls' window");
2009 LC("");
2010 LC(" ctrl + Button1 - zooms in");
2011 LC(" ctrl + Button2 - pans");
2012 LC(" ctrl + Button3 - zooms out");
2013 LC("");
2014 LC(" shift + Button1 - draws a square selection rectangle");
2015 LC(" shift + Button2 - freehand drawing tool");
2016 LC(" shift + ctrl + Button2 - draws lines");
2017 LC(" shift + Button3 - smudging tool");
2018 LC(" ");
2019 LC("Part 1a: Mouse Usage in Selection Rectangle");
2020 LC("--------------------------------------------");
2021 LC(" Button1 - moves selection rectangle");
2022 LC(" shift + Button1 - moves selection, constrains motion");
2023 LC(" Button2 - 'drag-and-drop' cut and paste");
2024 LC(" shift + Button2 - 'drag-and-drop' cut and paste, constrain");
2025 LC(" ctrl + Button2 - 'drag-and-drop' copy and paste");
2026 LC(" shift + ctrl + Button2 - 'drag-and-drop' copy and paste, constrain");
2027 LC("");
2028 LC("");
2029 LC("");
2030 LC("Part 2: Normal Keyboard Equivalents");
2031 LC("------------------------------------");
2032 LC("The following keys can be used in most xv windows, including the");
2033 LC("image, controls, and color editor windows, but *not* in the Visual");
2034 LC("Schnauzer windows.");
2035 LC("");
2036 LC(" Tab or");
2037 LC(" Space - 'Next' command");
2038 LC("");
2039 LC(" Return - reload currently displayed image file");
2040 LC("");
2041 LC(" Del or");
2042 LC(" Backspace - 'Prev' command");
2043 LC("");
2044 LC(" ctrl+'l' - 'Load' command");
2045 LC(" ctrl+'s' - 'Save' command");
2046 LC(" ctrl+'p' - 'Print' command");
2047 LC(" ctrl+'d' - 'Delete' command");
2048 LC("");
2049 LC(" 'q' or");
2050 LC(" ctrl+'q' - 'Quit' command");
2051 LC("");
2052 LC(" meta+'x' - 'cut' command");
2053 LC(" meta+'c' - 'copy' command");
2054 LC(" meta+'v' - 'paste' command");
2055 LC(" meta+'d' - 'clear' command");
2056 LC("");
2057 LC(" 'n' - reset image to normal (unexpanded) size");
2058 LC(" 'm' - maximum image size");
2059 LC(" 'M' - maximum image size, maintaining aspect ratio");
2060 LC(" '>' - double image size");
2061 LC(" '<' - half image size");
2062 LC(" '.' - make image 10% larger");
2063 LC(" ',' - make image 10% smaller");
2064 LC(" 'S' - set image to specified size/expansion");
2065 LC(" 'a' - reset image to normal aspect ratio");
2066 LC(" '4' - make image have a 4x3 width/height ratio");
2067 LC(" 'I' - round image size to integer expand/compres ratios");
2068 LC("");
2069 LC(" 't' - turn image 90 degrees clockwise");
2070 LC(" 'T' - turn image 90 degrees counter-clockwise");
2071 LC(" 'h' - flip image horizontally");
2072 LC(" 'v' - flip image vertically");
2073 LC("");
2074 LC(" 'P' - pad image");
2075 LC(" 'A' - image annotation");
2076 LC(" 'c' - 'Crop' command");
2077 LC(" 'u' - 'UnCrop' command");
2078 LC(" 'C' - 'AutoCrop' command");
2079 LC("");
2080 LC(" 'r' - raw mode");
2081 LC(" 'd' - dithered mode");
2082 LC(" 's' - smooth mode");
2083 LC(" meta+'8' - toggle 8/24 bit mode");
2084 LC("");
2085 LC(" 'V' or");
2086 LC(" ctrl+'v' - Visual Schnauzer");
2087 LC(" 'e' - Color Editor");
2088 LC(" 'i' - Image Info");
2089 LC(" ctrl+'c' - Image Comments");
2090 LC(" ctrl+'t' - Text View");
2091 LC("");
2092 LC(" ctrl+'g' - 'Grab' command");
2093 LC(" ctrl+'a' - 'About XV' command");
2094 LC("");
2095 LC(" meta+'b' - Blur algorithm");
2096 LC(" meta+'s' - Sharpen algorithm");
2097 LC(" meta+'e' - Edge Detection algorithm");
2098 LC(" meta+'m' - Emboss algorithm");
2099 LC(" meta+'o' - Oil Paint algorithm");
2100 LC(" meta+'B' - Blend algorithm");
2101 LC(" meta+'t' - Copy rotate algorithm");
2102 LC(" meta+'T' - Clear rotate algorithm");
2103 LC(" meta+'p' - Pixelize algorithm");
2104 LC(" meta+'S' - Spread algorithm");
2105 LC("");
2106 LC(" 'R' or");
2107 LC(" meta+'r' or");
2108 LC(" meta+'0' - 'Reset' command in color editor");
2109 LC("");
2110 LC(" meta+'1' - select preset 1 in color editor");
2111 LC(" meta+'2' - select preset 2 in color editor");
2112 LC(" meta+'3' - select preset 3 in color editor");
2113 LC(" meta+'4' - select preset 4 in color editor");
2114 LC(" meta+'a' - 'Apply' command in color editor");
2115 LC("");
2116 LC("");
2117 LC("");
2118 LC("Part 2a: Image Window Keys");
2119 LC("---------------------------");
2120 LC("The following keys can be used *only* inside the image window.");
2121 LC("");
2122 LC(" ctrl + Up - crops 1 pixel off the bottom of the image");
2123 LC(" ctrl + Down - crops 1 pixel off the top of the image");
2124 LC(" ctrl + Left - crops 1 pixel off the right side of the image");
2125 LC(" ctrl + Right - crops 1 pixel off the left side of the image");
2126 LC("");
2127 LC(" If you're viewing a multi-page document:");
2128 LC(" 'p' - opens a 'go to page #' dialog box");
2129 LC("");
2130 LC(" PageUp, or");
2131 LC(" Prev, or");
2132 LC(" shift+Up - previous page");
2133 LC("");
2134 LC(" PageDown, or");
2135 LC(" Next, or");
2136 LC(" shift+Down - next page");
2137 LC("");
2138 LC("");
2139 LC(" If a selection rectangle is active");
2140 LC(" Up - move rectangle up 1 pixel");
2141 LC(" Down - move rectangle down 1 pixel");
2142 LC(" Left - move rectangle left 1 pixel");
2143 LC(" Right - move rectangle right 1 pixel");
2144 LC(" shift+Up - shrink rectangle vertically by 1 pixel");
2145 LC(" shift+Down - expand rectangle vertically by 1 pixel");
2146 LC(" shift+Left - shrink rectangle horizontally by 1 pixel");
2147 LC(" shift+Right - expand rectangle horizontally by 1 pixel");
2148 LC("");
2149 LC("");
2150 LC("Part 2b: Visual Schnauzer Keys");
2151 LC("-------------------------------");
2152 LC("The following keys can be used only in the Visual Schnauzer windows.");
2153 LC("");
2154 LC(" ctrl+'d' - delete file(s)");
2155 LC(" ctrl+'n' - create new directory");
2156 LC(" ctrl+'r' - rename file");
2157 LC(" ctrl+'s' - rescan directory");
2158 LC(" ctrl+'w' - open new window");
2159 LC(" ctrl+'u' - update icons");
2160 LC(" ctrl+'g' - generate icons for selected files");
2161 LC(" ctrl+'a' - select all files");
2162 LC(" ctrl+'t' - view selected file as text");
2163 LC(" ctrl+'q' - quit XV");
2164 LC(" ctrl+'c' - change directory");
2165 LC(" ctrl+'f' - select filenames");
2166 LC(" ctrl+'e' - recursive update");
2167 LC(" Esc - close window");
2168 LC(" Return - load currently selected file(s)");
2169 LC(" Space - load next file");
2170 LC(" shift+Space - load next file, keeping previous file(s) selected");
2171 LC(" Backspace - load previous file");
2172
2173 #undef LC
2174 OpenTextView(keyhelp, (int) strlen(keyhelp), "XV Help", 0);
2175 }
2176
2177 #ifdef TV_MULTILINGUAL
2178
2179 #define TV_ML_ACCEPT TV_NCSS
2180 #define TV_ML_CLOSE (TV_ML_ACCEPT + 1)
2181 #define TV_ML_NBUTTS (TV_ML_CLOSE + 1)
2182
2183 #define TV_ML_RETCODE 0
2184 # define TV_ML_RET_LF 0
2185 # define TV_ML_RET_CRLF 1
2186 # define TV_ML_RET_CR 2
2187 # define TV_ML_RET_ANY 3
2188 #define TV_ML_GL 1
2189 #define TV_ML_GR 2
2190 #define TV_ML_CVTR 3
2191 #define TV_ML_NRBUTTS 4
2192
2193 #define TV_ML_SHORT 0
2194 #define TV_ML_LOCK 1
2195 #define TV_ML_NCBUTTS 2
2196
2197 #define TV_ML_NLISTS 4
2198
2199 #define CSWIDE (BUTTW3 * 5 + 5 * 6)
2200 #define CSHIGH 450
2201
2202 typedef struct csinfo_t {
2203 TVINFO *tv;
2204 RBUTT *rbt[TV_ML_NRBUTTS];
2205 CBUTT cbt[TV_ML_NCBUTTS];
2206 LIST ls[TV_ML_NLISTS];
2207 BUTT bt[TV_ML_NBUTTS];
2208 int up;
2209 Window win;
2210 struct coding_spec tcs; /* temporary coding_spec */
2211 } CSINFO;
2212 CSINFO csinfo[MAXTVWIN];
2213 static char **regs;
2214 static int nregs;
2215
2216 static int csCheckEvent PARM((CSINFO *, XEvent *));
2217 static void csReflect PARM((CSINFO *));
2218 static void csRedraw PARM((CSINFO *));
2219 static void csListRedraw PARM((LIST *));
2220 static void csLsRedraw PARM((int, SCRL *));
2221 static void create_registry_list PARM((void));
2222
2223 static char *(*cvtrtab[])PARM((char *, int, int *)) = {
2224 NULL,
2225 sjis_to_jis,
2226 };
2227
createCsWins(geom)2228 static void createCsWins(geom)
2229 const char *geom;
2230 {
2231 XSetWindowAttributes xswa;
2232 int i, j;
2233
2234 create_registry_list();
2235
2236 xswa.backing_store = WhenMapped;
2237 for (i = 0; i < MAXTVWIN; i++) {
2238 char nam[8];
2239 TVINFO *tv = &tinfo[i];
2240 CSINFO *cs = &csinfo[i];
2241 tv->cs = cs;
2242 cs->tv = tv;
2243 sprintf(nam, "XVcs%d", i);
2244 cs->win = CreateWindow("xv codeset", nam, geom,
2245 CSWIDE, CSHIGH, infofg, infobg, 0);
2246 if (!cs->win) FatalError("couldn't create 'charset' window!");
2247 #ifdef BACKING_STORE
2248 XChangeWindowAttributes(theDisp, cs->win, CWBackingStore, &xswa);
2249 #endif
2250 XSelectInput(theDisp, cs->win, ExposureMask | ButtonPressMask);
2251
2252 DrawString(cs->win, 5, 5 + ASCENT, "Initial States");
2253 for (i = 0; i < TV_ML_NLISTS; i++) {
2254 int x, y;
2255 char buf[80];
2256
2257 if (i / 2 == 0)
2258 x = 15;
2259 else
2260 x = 280;
2261 if (i % 2 == 0)
2262 y = 5 + LINEHIGH * 1;
2263 else
2264 y = 5 + LINEHIGH * 7 + SPACING * 3;
2265
2266 sprintf(buf, "Designation for G%d:", i + 1);
2267 DrawString(cs->win, x, y + ASCENT, buf);
2268
2269 LSCreate(&cs->ls[i], cs->win, x + 15, y + LINEHIGH,
2270 200, LINEHIGH * 5, 5,
2271 regs, nregs + 2,
2272 infofg, infobg, hicol, locol, csLsRedraw, 0, 0);
2273 cs->ls[i].selected = 0;
2274 }
2275
2276 for (i = 0; i < 2; i++) {
2277 char *p;
2278 int n;
2279 int x, y;
2280
2281 if ((p = (char *) malloc(3 * 4)) == NULL)
2282 FatalError("out of memory in createCsWins().");
2283 strcpy(p, "G1 G2 G3 G4");
2284 p[2] = p[5] = p[8] = '\0';
2285 n = (i == 0 ? TV_ML_GL : TV_ML_GR);
2286 x = (i == 0 ? 15 : 280);
2287 y = 235;
2288 DrawString(cs->win, x, y + ASCENT, "Assignment for GL:");
2289 x += 15;
2290 y += LINEHIGH;
2291 cs->rbt[n] = RBCreate(NULL, cs->win,
2292 x, y, p, infofg, infobg, hicol, locol);
2293 for (j = 1; j < 4; j++) {
2294 p += 3;
2295 x += 50;
2296 RBCreate(cs->rbt[n], cs->win,
2297 x, y, p, infofg, infobg, hicol, locol);
2298 }
2299 }
2300
2301 DrawString(cs->win, 5, 280 + ASCENT, "Ret Code:");
2302 cs->rbt[TV_ML_RETCODE] =
2303 RBCreate(NULL, cs->win, 20, 300, "LF", infofg,infobg, hicol,locol);
2304 RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 20, 300 + 20, "CR+LF",
2305 infofg, infobg, hicol, locol);
2306 RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 90, 300, "CR",
2307 infofg, infobg, hicol, locol);
2308 RBCreate(cs->rbt[TV_ML_RETCODE], cs->win, 90, 300 + 20, "Any",
2309 infofg, infobg, hicol, locol);
2310
2311 DrawString(cs->win, 350, 280 + ASCENT, "Converter:");
2312 cs->rbt[TV_ML_CVTR] =
2313 RBCreate(NULL, cs->win, 365, 300, "Nothing",
2314 infofg, infobg, hicol, locol);
2315 RBCreate(cs->rbt[TV_ML_CVTR], cs->win, 365, 300 + 20, "Shift JIS",
2316 infofg, infobg, hicol, locol);
2317
2318 CBCreate(&cs->cbt[TV_ML_SHORT], cs->win, 200, 300, "Short Form",
2319 infofg, infobg, hicol, locol);
2320 CBCreate(&cs->cbt[TV_ML_LOCK], cs->win, 200, 320, "Locking Shift",
2321 infofg, infobg, hicol, locol);
2322
2323 for (j = 0; j < TV_NCSS; j++) {
2324 BTCreate(&cs->bt[j], cs->win,
2325 5 + (BUTTW3 + 5) * (j % 5),
2326 350 + 5 + (BUTTH + 5) * (j / 5),
2327 BUTTW3, BUTTH, codeSetNames[j],
2328 infofg, infobg, hicol, locol);
2329 }
2330 BTCreate(&cs->bt[TV_ML_ACCEPT], cs->win,
2331 CSWIDE - 10 - BUTTW3 * 2, CSHIGH - 5 - BUTTH, BUTTW3, BUTTH,
2332 "Accept", infofg, infobg, hicol, locol);
2333 BTCreate(&cs->bt[TV_ML_CLOSE], cs->win,
2334 CSWIDE - 5 - BUTTW3, CSHIGH - 5 - BUTTH, BUTTW3, BUTTH,
2335 "Close", infofg, infobg, hicol, locol);
2336
2337 XMapSubwindows(theDisp, cs->win);
2338 cs->up = 0;
2339 }
2340 }
2341
openCsWin(tv)2342 static void openCsWin(tv)
2343 TVINFO *tv;
2344 {
2345 CSINFO *cs = tv->cs;
2346 if (cs->up)
2347 return;
2348
2349 XMapRaised(theDisp, cs->win);
2350 cs->up = 1;
2351 cs->tcs = cs->tv->ccs;
2352 csReflect(cs);
2353 }
2354
closeCsWin(tv)2355 static void closeCsWin(tv)
2356 TVINFO *tv;
2357 {
2358 CSINFO *cs = tv->cs;
2359 if (!cs->up)
2360 return;
2361 cs->up = 0;
2362 XUnmapWindow(theDisp, cs->win);
2363 }
2364
CharsetCheckEvent(xev)2365 int CharsetCheckEvent(xev)
2366 XEvent *xev;
2367 {
2368 int i;
2369 CSINFO *cs;
2370
2371 for (cs = csinfo, i = 0; i < MAXTVWIN; cs++, i++) {
2372 if (!cs->up)
2373 continue;
2374 if (csCheckEvent(cs, xev))
2375 break;
2376 }
2377 if (i < MAXTVWIN)
2378 return 1;
2379 return 0;
2380 }
2381
csCheckEvent(cs,xev)2382 static int csCheckEvent(cs, xev)
2383 CSINFO *cs;
2384 XEvent *xev;
2385 {
2386 RBUTT **rbp;
2387 CBUTT *cbp;
2388 LIST *ls;
2389 BUTT *bp;
2390 int i, n;
2391
2392 if (xev->type == Expose) {
2393 int x, y, w, h;
2394 XExposeEvent *e = (XExposeEvent *) xev;
2395 x = e->x; y = e->y; w = e->width; h = e->height;
2396
2397 if (cs->win == e->window){
2398 csRedraw(cs);
2399 return 1;
2400 } else {
2401 for (i = 0; i < TV_ML_NLISTS; i++) {
2402 if (cs->ls[i].win == e->window) {
2403 LSRedraw(&cs->ls[i], 0);
2404 return 1;
2405 }
2406 }
2407 for (i = 0; i < TV_ML_NLISTS; i++) {
2408 if (cs->ls[i].scrl.win == e->window) {
2409 SCRedraw(&cs->ls[i].scrl);
2410 return 1;
2411 }
2412 }
2413 }
2414 } else if (xev->type == ButtonPress) {
2415 int x, y;
2416 XButtonEvent *e = (XButtonEvent *) xev;
2417 x = e->x; y = e->y;
2418 if (cs->win == e->window) {
2419 for (bp = cs->bt, i = 0; i < TV_ML_NBUTTS; bp++, i++) {
2420 if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h))
2421 break;
2422 }
2423 if (i < TV_ML_NBUTTS) {
2424 if (BTTrack(bp)) {
2425 if (i < TV_NCSS) {
2426 cs->tcs = coding_spec[i];
2427 csReflect(cs);
2428 } else {
2429 switch (i) {
2430 case TV_ML_ACCEPT:
2431 setCodingSpec(cs->tv, &cs->tcs);
2432 break;
2433 case TV_ML_CLOSE:
2434 closeCsWin(cs->tv);
2435 break;
2436 }
2437 }
2438 }
2439 return 1;
2440 }
2441 for (cbp = cs->cbt, i = 0; i < TV_ML_NCBUTTS; cbp++, i++) {
2442 if (CBClick(cbp, x, y) && CBTrack(cbp))
2443 break;
2444 }
2445 if (i < TV_ML_NCBUTTS) {
2446 switch (i) {
2447 case TV_ML_SHORT:
2448 cs->tcs.coding_system.short_form = cbp->val;
2449 break;
2450 case TV_ML_LOCK:
2451 cs->tcs.coding_system.lock_shift = cbp->val;
2452 break;
2453 }
2454 return 1;
2455 }
2456 for (rbp = cs->rbt, i = 0; i < TV_ML_NRBUTTS; rbp++, i++) {
2457 if ((n = RBClick(*rbp, x, y)) >= 0 && RBTrack(*rbp, n)) {
2458 break;
2459 }
2460 }
2461 if (i < TV_ML_NRBUTTS) {
2462 switch (i) {
2463 case TV_ML_RETCODE:
2464 cs->tcs.coding_system.eol = n;
2465 break;
2466 case TV_ML_GL:
2467 cs->tcs.coding_system.gl = n;
2468 break;
2469 case TV_ML_GR:
2470 cs->tcs.coding_system.gr = n;
2471 break;
2472 case TV_ML_CVTR:
2473 cs->tcs.converter = cvtrtab[n];
2474 break;
2475 }
2476 return 1;
2477 }
2478 } else {
2479 for (ls = cs->ls, i = 0; i < TV_ML_NLISTS; ls++, i++) {
2480 if (ls->win == e->window) {
2481 LSClick(ls, e);
2482 n = ls->selected;
2483 if (n < nregs) {
2484 char r[32], *p = r;
2485 int b7;
2486 strcpy(r, regs[n]);
2487 if ((p = strrchr(r, '/')) != NULL) {
2488 *p = '\0';
2489 b7 = (*(p + 1) == 'R' ? 1 : 0);
2490 } else
2491 b7 = 0; /* shouldn't occur */
2492 cs->tcs.coding_system.design[i] = lookup_design(r, b7);
2493 } else if (n == nregs) /* initially none is designed. */
2494 cs->tcs.coding_system.design[i].bpc = 0;
2495 else
2496 cs->tcs.coding_system.design[i].bpc = -1;
2497 return 1;
2498 }
2499 }
2500 for (ls = cs->ls, i = 0; i < TV_ML_NLISTS; ls++, i++) {
2501 if (ls->scrl.win == e->window) {
2502 SCTrack(&ls->scrl, x, y);
2503 return 1;
2504 }
2505 }
2506 }
2507 }
2508 return 0;
2509 }
2510
csReflect(cs)2511 static void csReflect(cs)
2512 CSINFO *cs;
2513 {
2514 int i;
2515
2516 RBSelect(cs->rbt[TV_ML_RETCODE], cs->tcs.coding_system.eol);
2517 RBSelect(cs->rbt[TV_ML_GL], cs->tcs.coding_system.gl);
2518 RBSelect(cs->rbt[TV_ML_GR], cs->tcs.coding_system.gr);
2519 for (i = 0; i < sizeof cvtrtab / sizeof cvtrtab[0]; i++) {
2520 if (cs->tcs.converter == cvtrtab[i])
2521 break;
2522 }
2523 if (i >= sizeof cvtrtab / sizeof cvtrtab[0])
2524 FatalError("program error in csReflect().");
2525 RBSelect(cs->rbt[TV_ML_CVTR], i);
2526
2527 cs->cbt[TV_ML_SHORT].val = cs->tcs.coding_system.short_form;
2528 cs->cbt[TV_ML_LOCK].val = cs->tcs.coding_system.lock_shift;
2529 for (i = 0; i < TV_ML_NLISTS; i++) {
2530 struct design design = cs->tcs.coding_system.design[i];
2531 char *reg, r[32];
2532 int b7;
2533 int n = 0;
2534 switch (design.bpc) {
2535 case -1:
2536 n = nregs + 1;
2537 break;
2538 case 0:
2539 n = nregs;
2540 break;
2541 case 1:
2542 case 2:
2543 if ((reg = lookup_registry(design, &b7)) == NULL)
2544 FatalError("internal error in csReflect.");
2545 sprintf(r, "%s/%s", reg, b7 ? "Right" : "Left");
2546 for (n = 0; n < nregs; n++) {
2547 if (strcmp(regs[n], r) == 0)
2548 break;
2549 }
2550 }
2551 cs->ls[i].selected = n;
2552 ScrollToCurrent(&cs->ls[i]);
2553 }
2554 csRedraw(cs);
2555 for (i = 0; i < TV_ML_NLISTS; i++)
2556 csListRedraw(&cs->ls[i]);
2557 }
2558
csRedraw(cs)2559 static void csRedraw(cs)
2560 CSINFO *cs;
2561 {
2562 int i;
2563
2564 XSetForeground(theDisp, theGC, infofg);
2565 DrawString(cs->win, 5,5 + ASCENT, "Initial States");
2566 for (i = 0; i < TV_ML_NLISTS; i++) {
2567 int x, y;
2568 char buf[80];
2569
2570 if (i / 2 == 0)
2571 x = 15;
2572 else
2573 x = 280;
2574 if (i % 2 == 0)
2575 y = 5 + LINEHIGH * 1;
2576 else
2577 y = 5 + LINEHIGH * 7 + SPACING * 3;
2578
2579 sprintf(buf, "Designation for G%d:", i);
2580 DrawString(cs->win, x, y + ASCENT, buf);
2581 }
2582
2583 DrawString(cs->win, 15, 235 + ASCENT, "Invocation for GL:");
2584 DrawString(cs->win, 280, 235 + ASCENT, "Invocation for GR:");
2585 DrawString(cs->win, 5, 280 + ASCENT, "Ret Code:");
2586 DrawString(cs->win, 350, 280 + ASCENT, "Converter:");
2587
2588 for (i = 0; i < TV_ML_NBUTTS; i++)
2589 BTRedraw(&cs->bt[i]);
2590 for (i = 0; i < TV_ML_NCBUTTS; i++)
2591 CBRedraw(&cs->cbt[i]);
2592 for (i = 0; i < TV_ML_NRBUTTS; i++)
2593 RBRedraw(cs->rbt[i], -1);
2594 }
2595
csListRedraw(ls)2596 static void csListRedraw(ls)
2597 LIST *ls;
2598 {
2599 int i;
2600 for (i = 0; i < TV_ML_NLISTS; i++) {
2601 LSRedraw(ls, 0);
2602 SCRedraw(&ls->scrl);
2603 }
2604 }
2605
csLsRedraw(delta,sptr)2606 static void csLsRedraw(delta, sptr)
2607 int delta;
2608 SCRL *sptr;
2609 {
2610 int i, j;
2611 for (i = 0; i < MAXTVWIN; i++) {
2612 for (j = 0; j < TV_ML_NLISTS; j++) {
2613 if (sptr == &csinfo[i].ls[j].scrl) {
2614 LSRedraw(&csinfo[i].ls[j], delta);
2615 return;
2616 }
2617 }
2618 }
2619 }
2620
CharsetDelWin(win)2621 int CharsetDelWin(win)
2622 Window win;
2623 {
2624 CSINFO *cs;
2625 int i;
2626
2627 for (cs = csinfo, i = 0; i < TV_NCSS; cs++, i++) {
2628 if (cs->win == win) {
2629 if (cs->up) {
2630 XUnmapWindow(theDisp, cs->win);
2631 cs->up = 0;
2632 }
2633 return 1;
2634 }
2635 }
2636 return 0;
2637 }
2638
2639 static int reg_comp PARM((const void *, const void *));
create_registry_list()2640 static void create_registry_list()
2641 {
2642 struct design d;
2643 char *names, *p;
2644 int i;
2645
2646 if ((p = names = (char *) malloc(32 * 0x80 * 2 * 2)) == NULL)
2647 FatalError("out of memory in create_name_list#1.");
2648 nregs = 0;
2649 for (d.bpc = 1; d.bpc <=2; d.bpc++) {
2650 for (d.noc = 94; d.noc <= 96; d.noc += 2) {
2651 for (d.des = ' '; (unsigned char) d.des < 0x80; d.des++) {
2652 int b7;
2653 char *r;
2654 if ((r = lookup_registry(d, &b7)) != NULL) {
2655 sprintf(p, "%s/%s", r, b7 ? "Right" : "Left");
2656 p += strlen(p) + 1;
2657 nregs++;
2658 }
2659 }
2660 }
2661 }
2662 if ((names = (char *) realloc(names, (size_t) (p - names))) == NULL)
2663 FatalError("out of memory in create_name_list#2.");
2664 if ((regs = (char **) malloc(sizeof(char *) * (nregs + 3))) == NULL)
2665 FatalError("out of memory in create_name_list#3.");
2666 p = names;
2667 for (i = 0; i < nregs; i++) {
2668 regs[i] = p;
2669 p += strlen(p) + 1;
2670 }
2671 qsort(regs, (size_t) nregs, sizeof(char *), reg_comp);
2672 regs[i++] = "nothing";
2673 regs[i++] = "unused";
2674 regs[i++] = NULL;
2675 }
reg_comp(dst,src)2676 static int reg_comp(dst, src)
2677 const void *dst, *src;
2678 {
2679 return strcmp(*(char **) dst, *(char **) src);
2680 }
2681
2682 #endif /* TV_MULTILINGUAL */
2683