1 /* This file pager demo illustrates the screen management and
2 * keyboard routines.
3 */
4
5 #include <stdio.h>
6 #include <string.h>
7
8 #include <stdlib.h>
9
10 #include <signal.h>
11
12 #ifdef unix
13 # include <unistd.h>
14 #endif
15
16 #include <slang.h>
17
18 #include "demolib.c"
19
usage(char * pgm)20 static void usage (char *pgm)
21 {
22 fprintf (stderr, "Usage: %s [FILENAME]\n", pgm);
23 exit (1);
24 }
25
26 static int read_file (char *);
27 static void main_loop (void);
28
29 static char *File_Name; /* if NULL, use stdin */
30
main(int argc,char ** argv)31 int main (int argc, char **argv)
32 {
33 if (argc == 2)
34 {
35 File_Name = argv[1];
36 }
37 else if ((argc != 1) || (1 == isatty (fileno(stdin))))
38 usage (argv[0]);
39
40 if (-1 == read_file (File_Name))
41 {
42 fprintf (stderr, "Unable to read %s\n", File_Name);
43 return 1;
44 }
45
46 /* This sets up the terminal, signals, screen management routines, etc... */
47 if (-1 == demolib_init_terminal (1, 1))
48 {
49 fprintf (stderr, "Unable to initialize terminal.");
50 return 1;
51 }
52
53 #define APP_KEY_EOB 0x1001
54 #define APP_KEY_BOB 0x1002
55
56 /* Add a few application defined keysyms. 0x1000 and above are for
57 * applications.
58 */
59 (void) SLkp_define_keysym ("\033>", APP_KEY_EOB);
60 (void) SLkp_define_keysym ("\033<", APP_KEY_BOB);
61
62 main_loop (); /* should not return */
63 return 1;
64 }
65
66 /* The SLscroll routines will be used for pageup/down commands. They assume
67 * a linked list of lines. The first element of the structure MUST point to
68 * the NEXT line, the second MUST point to the PREVIOUS line.
69 */
70 typedef struct _File_Line_Type
71 {
72 struct _File_Line_Type *next;
73 struct _File_Line_Type *prev;
74 char *data; /* pointer to line data */
75 }
76 File_Line_Type;
77
78 static File_Line_Type *File_Lines;
79
80 /* The SLscroll routines will use this structure. */
81 static SLscroll_Window_Type Line_Window;
82
free_lines(void)83 static void free_lines (void)
84 {
85 File_Line_Type *line, *next;
86
87 line = File_Lines;
88 while (line != NULL)
89 {
90 next = line->next;
91 if (line->data != NULL) free (line->data);
92 free (line);
93 line = next;
94 }
95 File_Lines = NULL;
96 }
97
create_line(char * buf)98 static File_Line_Type *create_line (char *buf)
99 {
100 File_Line_Type *line;
101
102 line = (File_Line_Type *) malloc (sizeof (File_Line_Type));
103 if (line == NULL) return NULL;
104
105 memset ((char *) line, 0, sizeof (File_Line_Type));
106
107 line->data = SLmake_string (buf); /* use a slang routine */
108 if (line->data == NULL)
109 {
110 free (line);
111 return NULL;
112 }
113
114 return line;
115 }
116
read_file(char * file)117 static int read_file (char *file)
118 {
119 FILE *fp;
120 char buf [1024];
121 File_Line_Type *line, *last_line;
122 unsigned int num_lines;
123
124 if (file == NULL)
125 fp = stdin;
126 else fp = fopen (file, "r");
127
128 if (fp == NULL) return -1;
129
130 last_line = NULL;
131 num_lines = 0;
132
133 while (NULL != fgets (buf, sizeof(buf), fp))
134 {
135 num_lines++;
136
137 if (NULL == (line = create_line (buf)))
138 {
139 fprintf (stderr, "Out of memory.");
140 free_lines ();
141 return -1;
142 }
143
144 if (last_line == NULL)
145 File_Lines = line;
146 else
147 last_line->next = line;
148
149 line->prev = last_line;
150 line->next = NULL;
151
152 last_line = line;
153 }
154
155 memset ((char *)&Line_Window, 0, sizeof (SLscroll_Window_Type));
156
157 Line_Window.current_line = (SLscroll_Type *) File_Lines;
158 Line_Window.lines = (SLscroll_Type *) File_Lines;
159 Line_Window.line_num = 1;
160 Line_Window.num_lines = num_lines;
161 /* Line_Window.border = 3; */
162
163 return 0;
164 }
165
update_display(void)166 static void update_display (void)
167 {
168 unsigned int row, nrows;
169 File_Line_Type *line;
170
171 /* All well behaved applications should block signals that may affect
172 * the display while performing screen update.
173 */
174 SLsig_block_signals ();
175
176 Line_Window.nrows = nrows = SLtt_Screen_Rows - 1;
177
178 /* Always make the current line equal to the top window line. */
179 if (Line_Window.top_window_line != NULL)
180 Line_Window.current_line = Line_Window.top_window_line;
181
182 SLscroll_find_top (&Line_Window);
183
184 row = 0;
185 line = (File_Line_Type *) Line_Window.top_window_line;
186
187 SLsmg_normal_video ();
188
189 while (row < Line_Window.nrows)
190 {
191 SLsmg_gotorc (row, 0);
192
193 if (line != NULL)
194 {
195 SLsmg_write_string (line->data);
196 line = line->next;
197 }
198 SLsmg_erase_eol ();
199 row++;
200 }
201
202 SLsmg_gotorc (row, 0);
203 SLsmg_reverse_video ();
204 SLsmg_printf ("%s | UTF-8 = %d",
205 (File_Name == NULL) ? "<stdin>" : File_Name,
206 SLutf8_is_utf8_mode ());
207 SLsmg_erase_eol ();
208 SLsmg_refresh ();
209
210 SLsig_unblock_signals ();
211 }
212
213 static int Screen_Start;
214
main_loop(void)215 static void main_loop (void)
216 {
217 int screen_start;
218
219 while (1)
220 {
221 update_display ();
222 switch (SLkp_getkey ())
223 {
224 case SL_KEY_ERR:
225 case 'q':
226 case 'Q':
227 demolib_exit (0);
228 break;
229
230 case SL_KEY_RIGHT:
231 Screen_Start += 1;
232 screen_start = Screen_Start;
233 SLsmg_set_screen_start (NULL, &screen_start);
234 break;
235
236 case SL_KEY_LEFT:
237 Screen_Start -= 1;
238 if (Screen_Start < 0) Screen_Start = 0;
239 screen_start = Screen_Start;
240 SLsmg_set_screen_start (NULL, &screen_start);
241 break;
242
243 case SL_KEY_UP:
244 SLscroll_prev_n (&Line_Window, 1);
245 Line_Window.top_window_line = Line_Window.current_line;
246 break;
247
248 case '\r':
249 case SL_KEY_DOWN:
250 SLscroll_next_n (&Line_Window, 1);
251 Line_Window.top_window_line = Line_Window.current_line;
252 break;
253
254 case SL_KEY_NPAGE:
255 case ' ': case 4:
256 SLscroll_pagedown (&Line_Window);
257 break;
258
259 case SL_KEY_PPAGE:
260 case 127: case 21:
261 SLscroll_pageup (&Line_Window);
262 break;
263
264 case APP_KEY_BOB:
265 while (-1 != SLscroll_pageup (&Line_Window))
266 ;
267 break;
268
269 case APP_KEY_EOB:
270 while (-1 != SLscroll_pagedown (&Line_Window))
271 ;
272 break;
273
274 default:
275 SLtt_beep ();
276 }
277 }
278 }
279