1 /*
2  * text.c
3  *
4  * Text manipulation routines
5  *
6  */
7 
8 #include "ztypes.h"
9 
10 static int saved_formatting = ON;
11 /* static int line_pos = 0; */
12 /* static int char_count = 0; no longer used --zarf */
13 static int story_buffer = 0;
14 static int story_pos = 0;
15 static int story_count = 0;
16 
17 /*
18  * decode_text
19  *
20  * Convert encoded text to ASCII. Text is encoded by squeezing each character
21  * into 5 bits. 3 x 5 bit encoded characters can fit in one word with a spare
22  * bit left over. The spare bit is used to signal to end of a string. The 5 bit
23  * encoded characters can either be actual character codes or prefix codes that
24  * modifier the following code.
25  *
26  */
27 
28 #ifdef __STDC__
decode_text(unsigned long * address)29 void decode_text (unsigned long *address)
30 #else
31 void decode_text (address)
32 unsigned long *address;
33 #endif
34 {
35     int i, synonym_flag, synonym = 0, ascii_flag, ascii = 0;
36     int data, code, shift_state, shift_lock;
37     unsigned long addr;
38 
39     /* Set state variables */
40 
41     shift_state = 0;
42     shift_lock = 0;
43     ascii_flag = 0;
44     synonym_flag = 0;
45 
46     do {
47 
48         /*
49          * Read one 16 bit word. Each word contains three 5 bit codes. If the
50          * high bit is set then this is the last word in the string.
51          */
52 
53         data = read_data_word (address);
54 
55         for (i = 10; i >= 0; i -= 5) {
56 
57             /* Get code, high bits first */
58 
59             code = (data >> i) & 0x1f;
60 
61             /* Synonym codes */
62 
63             if (synonym_flag) {
64 
65                 synonym_flag = 0;
66                 synonym = (synonym - 1) * 64;
67                 addr = (unsigned long) get_word (h_synonyms_offset + synonym + (code * 2)) * 2;
68                 decode_text (&addr);
69                 shift_state = shift_lock;
70 
71             /* ASCII codes */
72 
73             } else if (ascii_flag) {
74 
75                 /*
76                  * If this is the first part ASCII code then remember it.
77                  * Because the codes are only 5 bits you need two codes to make
78                  * one eight bit ASCII character. The first code contains the
79                  * top 3 bits. The second code contains the bottom 5 bits.
80                  */
81 
82                 if (ascii_flag++ == 1)
83 
84                     ascii = code << 5;
85 
86                 /*
87                  * If this is the second part ASCII code then assemble the
88                  * character from the two codes and output it.
89                  */
90 
91                 else {
92 
93                     ascii_flag = 0;
94                     write_zchar ((char) (ascii | code));
95 
96                 }
97 
98             /* Character codes */
99 
100             } else if (code > 5) {
101 
102                 code -= 6;
103 
104                 /*
105                  * If this is character 0 in the punctuation set then the next two
106                  * codes make an ASCII character.
107                  */
108 
109                 if (shift_state == 2 && code == 0)
110 
111                     ascii_flag = 1;
112 
113                 /*
114                  * If this is character 1 in the punctuation set then this
115                  * is a new line.
116                  */
117 
118                 else if (shift_state == 2 && code == 1 && h_type > V1)
119 
120                     new_line ();
121 
122                 /*
123                  * This is a normal character so select it from the character
124                  * table appropriate for the current shift state.
125                  */
126 
127                 else
128 
129                     write_zchar (lookup_table[shift_state][code]);
130 
131                 shift_state = shift_lock;
132 
133             /* Special codes 0 to 5 */
134 
135             } else {
136 
137                 /*
138                  * Space: 0
139                  *
140                  * Output a space character.
141                  *
142                  */
143 
144                 if (code == 0) {
145 
146                     write_zchar (' ');
147 
148                 } else {
149 
150                     /*
151                      * The use of the synonym and shift codes is the only difference between
152                      * the different versions.
153                      */
154 
155                     if (h_type < V3) {
156 
157                         /*
158                          * Newline or synonym: 1
159                          *
160                          * Output a newline character or set synonym flag.
161                          *
162                          */
163 
164                         if (code == 1) {
165 
166                             if (h_type == V1)
167 
168                                 new_line ();
169 
170                             else {
171 
172                                 synonym_flag = 1;
173                                 synonym = code;
174 
175                             }
176 
177                         /*
178                          * Shift keys: 2, 3, 4 or 5
179                          *
180                          * Shift keys 2 & 3 only shift the next character and can be used regardless of
181                          * the state of the shift lock. Shift keys 4 & 5 lock the shift until reset.
182                          *
183                          * The following code implements the the shift code state transitions:
184                          *
185                          *               +-------------+-------------+-------------+-------------+
186                          *               |       Shift   State       |        Lock   State       |
187                          * +-------------+-------------+-------------+-------------+-------------+
188                          * | Code        |      2      |       3     |      4      |      5      |
189                          * +-------------+-------------+-------------+-------------+-------------+
190                          * | lowercase   | uppercase   | punctuation | uppercase   | punctuation |
191                          * | uppercase   | punctuation | lowercase   | punctuation | lowercase   |
192                          * | punctuation | lowercase   | uppercase   | lowercase   | uppercase   |
193                          * +-------------+-------------+-------------+-------------+-------------+
194                          *
195                          */
196 
197                         } else {
198                             if (code < 4)
199                                 shift_state = (shift_lock + code + 2) % 3;
200                             else
201                                 shift_lock = shift_state = (shift_lock + code) % 3;
202                         }
203 
204                     } else {
205 
206                         /*
207                          * Synonym table: 1, 2 or 3
208                          *
209                          * Selects which of three synonym tables the synonym
210                          * code following in the next code is to use.
211                          *
212                          */
213 
214                         if (code < 4) {
215 
216                             synonym_flag = 1;
217                             synonym = code;
218 
219                         /*
220                          * Shift key: 4 or 5
221                          *
222                          * Selects the shift state for the next character,
223                          * either uppercase (4) or punctuation (5). The shift
224                          * state automatically gets reset back to lowercase for
225                          * V3+ games after the next character is output.
226                          *
227                          */
228 
229                         } else {
230 
231                             shift_state = code - 3;
232                             shift_lock = 0;
233 
234                         }
235                     }
236                 }
237             }
238         }
239     } while ((data & 0x8000) == 0);
240 
241 }/* decode_text */
242 
243 /*
244  * encode_text
245  *
246  * Pack a string into up to 9 codes or 3 words.
247  *
248  */
249 
250 #ifdef __STDC__
encode_text(int len,const char * s,short * buffer)251 void encode_text (int len, const char *s, short *buffer)
252 #else
253 void encode_text (len, s, buffer)
254 int len;
255 const char *s;
256 short *buffer;
257 #endif
258 {
259     int i, j, prev_table, table, next_table, shift_state, code, codes_count;
260     char codes[9];
261 
262     /* Initialise codes count and prev_table number */
263 
264     codes_count = 0;
265     prev_table = 0;
266 
267     /* Scan do the string one character at a time */
268 
269     while (len--) {
270 
271         /*
272          * Set the table and code to be the ASCII character inducer, then
273          * look for the character in the three lookup tables. If the
274          * character isn't found then it will be an ASCII character.
275          */
276 
277         table = 2;
278         code = 0;
279         for (i = 0; i < 3; i++) {
280             for (j = 0; j < 26; j++) {
281                 if (lookup_table[i][j] == *s) {
282                     table = i;
283                     code = j;
284                 }
285             }
286         }
287 
288         /*
289          * Type 1 and 2 games differ on how the shift keys are used. Switch
290          * now depending on the game version.
291          */
292 
293         if (h_type < V3) {
294 
295             /*
296              * If the current table is the same as the previous table then
297              * just store the character code, otherwise switch tables.
298              */
299 
300             if (table != prev_table) {
301 
302                 /* Find the table for the next character */
303 
304                 next_table = 0;
305                 if (len) {
306                     next_table = 2;
307                     for (i = 0; i < 3; i++) {
308                         for (j = 0; j < 26; j++) {
309                             if (lookup_table[i][j] == s[1])
310                                 next_table = i;
311                         }
312                     }
313                 }
314 
315                 /*
316                  * Calculate the shift key. This magic. See the description in
317                  * decode_text for more information on version 1 and 2 shift
318                  * key changes.
319                  */
320 
321                 shift_state = (table + (prev_table * 2)) % 3;
322 
323                 /* Only store the shift key if there is a change in table */
324 
325                 if (shift_state) {
326 
327                     /*
328                      * If the next character as the uses the same table as
329                      * this character then change the shift from a single
330                      * shift to a shift lock. Also remember the current
331                      * table for the next iteration.
332                      */
333 
334                     if (next_table == table) {
335                         shift_state += 2;
336                         prev_table = table;
337                     } else
338                         prev_table = 0;
339 
340                     /* Store the code in the codes buffer */
341 
342                     if (codes_count < 9)
343                         codes[codes_count++] = (char) (shift_state + 1);
344                 }
345             }
346         } else {
347 
348             /*
349              * For V3 games each uppercase or punctuation table is preceded
350              * by a separate shift key. If this is such a shift key then
351              * put it in the codes buffer.
352              */
353 
354             if (table && codes_count < 9)
355                 codes[codes_count++] = (char) (table + 3);
356         }
357 
358         /* Put the character code in the code buffer */
359 
360         if (codes_count < 9)
361             codes[codes_count++] = (char) (code + 6);
362 
363         /*
364          * Cannot find character in table so treat it as a literal ASCII
365          * code. The ASCII code inducer (code 0 in table 2) is followed by
366          * the high 3 bits of the ASCII character followed by the low 5
367          * bits to make 8 bits in total.
368          */
369 
370         if (table == 2 && code == 0) {
371             if (codes_count < 9)
372                 codes[codes_count++] = (char) ((*s >> 5) & 0x07);
373             if (codes_count < 9)
374                 codes[codes_count++] = (char) (*s & 0x1f);
375         }
376 
377         /* Advance to next character */
378 
379         s++;
380 
381     }
382 
383     /* Pad out codes with shift 5's */
384 
385     while (codes_count < 9)
386         codes[codes_count++] = 5;
387 
388     /* Pack codes into buffer */
389 
390     buffer[0] = ((short) codes[0] << 10) | ((short) codes[1] << 5) | (short) codes[2];
391     buffer[1] = ((short) codes[3] << 10) | ((short) codes[4] << 5) | (short) codes[5];
392     buffer[2] = ((short) codes[6] << 10) | ((short) codes[7] << 5) | (short) codes[8];
393 
394     /* Terminate buffer at 6 or 9 codes depending on the version */
395 
396     if (h_type < V4)
397         buffer[1] |= 0x8000;
398     else
399         buffer[2] |= 0x8000;
400 
401 }/* encode_text */
402 
403 /*
404  * write_zchar
405  *
406  * High level Z-code character output routine. Translates Z-code characters to
407  * machine specific character(s) before output. If it cannot translate it then
408  * use the default translation. If the character is still unknown then display
409  * a '?'.
410  *
411  */
412 
413 #ifdef __STDC__
write_zchar(int c)414 void write_zchar (int c)
415 #else
416 void write_zchar (c)
417 int c;
418 #endif
419 {
420     char xlat_buffer[MAX_TEXT_SIZE + 1];
421     int i;
422 
423     c = (unsigned int) (c & 0xff);
424 
425     /* If character is not special character then just write it */
426 
427     if (c >= ' ' && c <= '~') {
428 
429         write_char (c);
430 
431     }
432     else if (c == 13) {
433 
434         /* write_char ('\r'); */
435         new_line ();
436 
437     }
438     else {
439 
440         /* Put default character in translation buffer */
441 
442         xlat_buffer[0] = '?';
443         xlat_buffer[1] = '\0';
444 
445         /* If translation fails then supply a default */
446 
447         if (codes_to_text (c, xlat_buffer)) {
448 
449             if (c > 23 && c < 28) {
450 	        /* Arrow keys - these must the keyboard keys used for input */
451 	        static char xlat[4] = { '\\', '/', '+', '-' };
452 
453                 xlat_buffer[0] = xlat[c - 24];
454                 xlat_buffer[1] = '\0';
455             }
456             else if (c == 0) {
457             	/* Null - print nothing */
458                 xlat_buffer[0] = '\0';
459             }
460             else if (c < 32) {
461             	/* Some other control character: print an octal escape. */
462             	xlat_buffer[0] = '\\';
463                 xlat_buffer[1] = '0' + ((c >> 6) & 7);
464                 xlat_buffer[2] = '0' + ((c >> 3) & 7);
465                 xlat_buffer[3] = '0' + (c & 7);
466                 xlat_buffer[4] = '\0';
467             }
468             else if (c > 178 && c < 219) {
469                 /* IBM line drawing characters to ASCII characters */
470                 if (c == 179)
471                     xlat_buffer[0] = '|';
472                 else if (c == 186)
473                     xlat_buffer[0] = '#';
474                 else if (c == 196)
475                     xlat_buffer[0] = '-';
476                 else if (c == 205)
477                     xlat_buffer[0] = '=';
478                 else
479                     xlat_buffer[0] = '+';
480                 xlat_buffer[1] = '\0';
481             }
482             else if (c > 154 && c < 164) {
483                 /* German character replacements */
484 
485                 static char xlat[] = "aeoeueAeOeUess>><<";
486 
487                 xlat_buffer[0] = xlat[((c - 155) * 2) + 0];
488                 xlat_buffer[1] = xlat[((c - 155) * 2) + 1];
489                 xlat_buffer[2] = '\0';
490             }
491         }
492 
493         /* Substitute translated characters */
494 
495         for (i = 0; xlat_buffer[i] != '\0'; i++)
496             write_char ((unsigned char) xlat_buffer[i]);
497 
498     }
499 
500 }/* write_zchar */
501 
502 /*
503  * write_char
504  *
505  * High level character output routine. The write_char routine is slightly
506  * complicated by the fact that the output can be limited by a fixed character
507  * count, as well as, filling up the buffer.
508  *
509  */
510 
511 #ifdef __STDC__
write_char(int c)512 void write_char (int c)
513 #else
514 void write_char (c)
515 int c;
516 #endif
517 {
518     char *cp;
519     int right_len;
520 
521     /* Only do if text formatting is turned on */
522 
523     if (redirect_depth) {
524 
525         /* If redirect is on then write the character to the status line for V1 to V3
526            games or into the writeable data area for V4+ games */
527 
528         if (h_type < V4)
529             status_line[status_pos++] = (char) c;
530         else {
531             set_byte (story_pos++, c);
532             story_count++;
533         }
534     } else {
535 
536         /* No formatting or output redirection, so just output the character */
537 
538         if (c == 13)
539           c = '\n';
540 
541         script_char (c);
542 
543         output_char (c);
544 
545     }
546 
547 }/* write_char */
548 
549 /*
550  * set_video_attribute
551  *
552  * Set a video attribute. Write the video mode, from 0 to 8, incremented.
553  * This is so the output routines don't confuse video attribute 0 as the
554  * end of the string.
555  *
556  */
557 
558 #ifdef __STDC__
set_video_attribute(zword_t mode)559 void set_video_attribute (zword_t mode)
560 #else
561 void set_video_attribute (mode)
562 zword_t mode;
563 #endif
564 {
565 
566     if ((int) mode <= MAX_ATTRIBUTE)
567         write_char ((char) ++mode);
568 
569 }/* set_video_attribute */
570 
571 /*
572  * write_string
573  *
574  * Output a string
575  *
576  */
577 
578 #ifdef __STDC__
write_string(const char * s)579 void write_string (const char *s)
580 #else
581 void write_string (s)
582 const char *s;
583 #endif
584 {
585 
586     while (*s)
587         write_zchar (*s++);
588 
589 }/* write_string */
590 
591 /*
592  * flush_buffer
593  *
594  * Send output buffer to the screen.
595  *
596  */
597 
598 #ifdef __STDC__
flush_buffer(int flag)599 void flush_buffer (int flag)
600 #else
601 void flush_buffer (flag)
602 int flag;
603 #endif
604 {
605 
606     /* Terminate the line */
607     /* ain't no bufferin' no more --zarf */
608 
609 #if 0
610     line[line_pos] = '\0';
611 
612     /* Send the line buffer to the printer */
613 
614     script_string (line);
615 
616     /* Send the line buffer to the screen */
617 
618     output_string (line);
619 
620     /* Reset the buffer pointer */
621 
622     line_pos = 0;
623 #endif
624 
625 }/* flush_buffer */
626 
627 /*
628  * set_format_mode
629  *
630  * Set the format mode flag. Formatting disables writing into the output buffer.
631  *
632  */
633 
634 #ifdef __STDC__
set_format_mode(zword_t flag)635 void set_format_mode (zword_t flag)
636 #else
637 void set_format_mode (flag)
638 zword_t flag;
639 #endif
640 {
641 
642     /* Flush any current output */
643 
644     flush_buffer (FALSE);
645 
646     /* Set formatting depending on the flag */
647 
648     if (flag)
649         formatting = ON;
650     else
651         formatting = OFF;
652 
653 }/* set_format_mode */
654 
655 /*
656  * set_print_modes
657  *
658  * Set various printing modes. These can be: disabling output, scripting and
659  * redirecting output. Redirection is peculiar. I use it to format the status
660  * line for V1 to V3 games, otherwise it wasn't used. V4 games format the status line
661  * themselves in an internal buffer in the writeable data area. To use the normal
662  * text decoding routines they have to redirect output to the writeable data
663  * area. This is done by passing in a buffer pointer. The first word of the
664  * buffer will receive the number of characters written since the output was
665  * redirected. The remainder of the buffer will contain the redirected text.
666  *
667  */
668 
669 typedef struct redirect_stash_struct {
670     zword_t count;
671     zword_t buffer;
672     zword_t pos;
673 } redirect_stash_t;
674 
675 #ifdef __STDC__
set_print_modes(zword_t type,zword_t option)676 void set_print_modes (zword_t type, zword_t option)
677 #else
678 void set_print_modes (type, option)
679 zword_t type;
680 zword_t option;
681 #endif
682 {
683     static int redirect_size = 0;
684     static redirect_stash_t *stash = NULL;
685 
686     if ((short) type == 1) {
687 
688         /* Turn on text output */
689 
690         outputting = ON;
691 
692     } else if ((short) type == 2) {
693 
694         /* Turn on scripting */
695 
696         open_script ();
697 
698     } else if ((short) type == 3) {
699 
700         /* Turn on output redirection */
701 
702         if (redirect_depth == 0) {
703 	    /* Disable text formatting during redirection */
704 
705 	    saved_formatting = formatting;
706 	    formatting = OFF;
707 
708 	    /* Enable text redirection */
709 
710 	    redirect_depth = 1;
711 	}
712 	else {
713 	    if (redirect_size == 0) {
714 	        redirect_size = 4;
715 		stash = (redirect_stash_t *)malloc(
716 		    redirect_size * sizeof(redirect_stash_t));
717 	    }
718 	    if (redirect_depth > redirect_size) {
719 	        redirect_size *= 2;
720 		stash = (redirect_stash_t *)realloc(stash,
721 		    redirect_size * sizeof(redirect_stash_t));
722 	    }
723 
724 	    if (h_type < V4) {
725   	        stash[redirect_depth-1].pos = status_pos;
726 	    }
727 	    else {
728 	        stash[redirect_depth-1].pos = story_pos;
729 		stash[redirect_depth-1].buffer = story_buffer;
730 		stash[redirect_depth-1].count = story_count;
731 	    }
732 
733 	    redirect_depth++;
734 	}
735 
736         /* Set up the redirection pointers */
737 
738         if (h_type < V4)
739             status_pos = 0;
740         else {
741             story_count = 0;
742             story_buffer = option;
743             story_pos = option + 2;
744         }
745 
746     } else if ((short) type == 4) {
747 
748         /* Turn on input recording */
749 
750         open_record ();
751 
752     } else if ((short) type == -1) {
753 
754         /* Turn off text output */
755 
756         outputting = OFF;
757 
758     } else if ((short) type == -2) {
759 
760         /* Turn off scripting */
761 
762         close_script ();
763 
764     } else if ((short) type == -3) {
765 
766         /* Turn off output redirection */
767 
768         if (redirect_depth) {
769 
770   	    if (redirect_depth == 1) {
771 	        /* Restore the format mode and turn off redirection */
772 
773 	        formatting = saved_formatting;
774 		redirect_depth = 0;
775 
776 		/* Terminate the redirection buffer and store the count of
777 		   character in the buffer into the first word of the buffer */
778 
779 		if (h_type > V3)
780 		    set_word (story_buffer, story_count);
781 	    }
782 	    else {
783 	        if (h_type > V3)
784 		    set_word (story_buffer, story_count);
785 
786 		redirect_depth--;
787 
788 		if (h_type < V4) {
789 		    status_pos = stash[redirect_depth-1].pos;
790 		}
791 		else {
792 		    story_pos = stash[redirect_depth-1].pos;
793 		    story_buffer = stash[redirect_depth-1].buffer;
794 		    story_count = stash[redirect_depth-1].count;
795 		}
796 
797 	    }
798         }
799 
800     } else if ((short) type == -4) {
801 
802         /* Turn off input recording */
803 
804         close_record ();
805 
806     }
807 
808 }/* set_print_modes */
809 
810 /*
811  * print_character
812  *
813  * Write a character.
814  *
815  */
816 
817 #ifdef __STDC__
print_character(zword_t c)818 void print_character (zword_t c)
819 #else
820 void print_character (c)
821 zword_t c;
822 #endif
823 {
824 
825     write_zchar ((char) c);
826 
827 }/* print_character */
828 
829 /*
830  * print_number
831  *
832  * Write a signed number.
833  *
834  */
835 
836 #ifdef __STDC__
print_number(zword_t num)837 void print_number (zword_t num)
838 #else
839 void print_number (num)
840 zword_t num;
841 #endif
842 {
843     int i, count;
844     char buffer[10];
845 
846     i = (short) num;
847     sprintf (buffer, "%d", i);
848     count = strlen (buffer);
849     for (i = 0; i < count; i++)
850         write_char (buffer[i]);
851 
852 }/* print_number */
853 
854 /*
855  * print_address
856  *
857  * Print using a packed address. Packed addresses are used to save space and
858  * reference addresses outside of the data region.
859  *
860  */
861 
862 #ifdef __STDC__
print_address(zword_t packed_address)863 void print_address (zword_t packed_address)
864 #else
865 void print_address (packed_address)
866 zword_t packed_address;
867 #endif
868 {
869     unsigned long address;
870 
871     /* Convert packed address to real address */
872 
873     address = (unsigned long) packed_address * story_scaler;
874 
875     /* Decode and output text at address */
876 
877     decode_text (&address);
878 
879 }/* print_address */
880 
881 /*
882  * print_offset
883  *
884  * Print using a real address. Real addresses are just offsets into the
885  * data region.
886  *
887  */
888 
889 #ifdef __STDC__
print_offset(zword_t offset)890 void print_offset (zword_t offset)
891 #else
892 void print_offset (offset)
893 zword_t offset;
894 #endif
895 {
896     unsigned long address;
897 
898     address = offset;
899 
900     /* Decode and output text at address */
901 
902     decode_text (&address);
903 
904 }/* print_offset */
905 
906 /*
907  * print_object
908  *
909  * Print an object description. Object descriptions are stored as ASCIC
910  * strings at the front of the property list for the object.
911  *
912  */
913 
914 #ifdef __STDC__
print_object(zword_t obj)915 void print_object (zword_t obj)
916 #else
917 void print_object (obj)
918 zword_t obj;
919 #endif
920 {
921     zword_t offset;
922     unsigned long address;
923 
924     /* Check for NULL object */
925 
926     if (obj == 0)
927         return;
928 
929     /* Calculate address of property list */
930 
931     offset = get_object_address (obj);
932     offset += (h_type < V4) ? O3_PROPERTY_OFFSET : O4_PROPERTY_OFFSET;
933 
934     /* Read the property list address and skip the count byte */
935 
936     address = (unsigned long) get_word (offset) + 1;
937 
938     /* Decode and output text at address */
939 
940     decode_text (&address);
941 
942 }/* print_object */
943 
944 /*
945  * print_literal
946  *
947  * Print the string embedded in the instruction stream at this point. All
948  * strings that do not need to be referenced by address are embedded in the
949  * instruction stream. All strings that can be refered to by address are placed
950  * at the end of the code region and referenced by packed address.
951  *
952  */
953 
954 #ifdef __STDC__
print_literal(void)955 void print_literal (void)
956 #else
957 void print_literal ()
958 #endif
959 {
960 
961     /* Decode and output text at PC */
962 
963     decode_text (&pc);
964 
965 }/* print_literal */
966 
967 /*
968  * println_return
969  *
970  * Print a string embedded in the instruction stream as with print_literal,
971  * except flush the output buffer and write a new line. After this return from
972  * the current subroutine with a status of true.
973  *
974  */
975 
976 #ifdef __STDC__
println_return(void)977 void println_return (void)
978 #else
979 void println_return ()
980 #endif
981 {
982 
983     print_literal ();
984     new_line ();
985     ret (TRUE);
986 
987 }/* println_return */
988 
989 /*
990  * new_line
991  *
992  * Simply flush the current contents of the output buffer followed by a new
993  * line.
994  *
995  */
996 
997 #ifdef __STDC__
new_line(void)998 void new_line (void)
999 #else
1000 void new_line ()
1001 #endif
1002 {
1003 
1004     /* Only flush buffer if story redirect is off */
1005 
1006     if (redirect_depth == 0) {
1007         flush_buffer (TRUE);
1008         script_new_line ();
1009         output_new_line ();
1010     } else
1011         write_char ('\r');
1012 
1013 }/* new_line */
1014 
1015 /*
1016  * print_time
1017  *
1018  * Print the time as HH:MM [am|pm]. This is a bit language dependent and can
1019  * quite easily be changed. If you change the size of the time string output
1020  * then adjust the status line position in display_status_line.
1021  *
1022  */
1023 
1024 #ifdef __STDC__
print_time(int hours,int minutes)1025 void print_time (int hours, int minutes)
1026 #else
1027 void print_time (hours, minutes)
1028 int hours;
1029 int minutes;
1030 #endif
1031 {
1032     int pm_indicator;
1033 
1034     /* Remember if time is pm */
1035 
1036     pm_indicator = (hours < 12) ? OFF : ON;
1037 
1038     /* Convert 24 hour clock to 12 hour clock */
1039 
1040     hours %= 12;
1041     if (hours == 0)
1042         hours = 12;
1043 
1044     /* Write hour right justified */
1045 
1046     if (hours < 10)
1047         write_char (' ');
1048     print_number (hours);
1049 
1050     /* Write hours/minutes separator */
1051 
1052     write_char (':');
1053 
1054     /* Write minutes zero filled */
1055 
1056     if (minutes < 10)
1057         write_char ('0');
1058     print_number (minutes);
1059 
1060     /* Write the am or pm string */
1061 
1062     if (pm_indicator == ON)
1063         write_string (" pm");
1064     else
1065         write_string (" am");
1066 
1067 }/* print_time */
1068 
1069 /*
1070  * encode
1071  *
1072  * Convert text to packed text.
1073  *
1074  */
1075 
1076 #ifdef __STDC__
encode(zword_t word_addr,zword_t word_length,zword_t word_offset,zword_t dest_addr)1077 void encode (zword_t word_addr, zword_t word_length, zword_t word_offset, zword_t dest_addr)
1078 #else
1079 void encode (word_addr, word_length, word_offset, dest_addr)
1080 zword_t word_addr;
1081 zword_t word_length;
1082 zword_t word_offset;
1083 zword_t dest_addr;
1084 #endif
1085 {
1086     short word[3];
1087     int i;
1088 
1089     /* Encode the word */
1090 
1091     encode_text (word_length, (const char *) &datap[word_addr + word_offset], word);
1092 
1093     /* Move the encoded word, byte swapped, into the destination buffer */
1094 
1095     for (i = 0; i < 3; i++, dest_addr += 2)
1096         set_word (dest_addr, word[i]);
1097 
1098 }/* encode */
1099