~ubuntu-branches/ubuntu/quantal/less/quantal

« back to all changes in this revision

Viewing changes to output.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Schoepf
  • Date: 2002-04-04 16:43:52 UTC
  • Revision ID: james.westby@ubuntu.com-20020404164352-qldq048yoc7x5sd5
Tags: upstream-374
ImportĀ upstreamĀ versionĀ 374

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1984-2000  Mark Nudelman
 
3
 *
 
4
 * You may distribute under the terms of either the GNU General Public
 
5
 * License or the Less License, as specified in the README file.
 
6
 *
 
7
 * For more information about less, or for information on how to 
 
8
 * contact the author, see the README file.
 
9
 */
 
10
 
 
11
 
 
12
/*
 
13
 * High level routines dealing with the output to the screen.
 
14
 */
 
15
 
 
16
#include "less.h"
 
17
#if MSDOS_COMPILER==WIN32C
 
18
#include "windows.h"
 
19
#endif
 
20
 
 
21
public int errmsgs;     /* Count of messages displayed by error() */
 
22
public int need_clr;
 
23
public int final_attr;
 
24
 
 
25
extern int sigs;
 
26
extern int sc_width;
 
27
extern int so_s_width, so_e_width;
 
28
extern int screen_trashed;
 
29
extern int any_display;
 
30
extern int is_tty;
 
31
 
 
32
/*
 
33
 * Display the line which is in the line buffer.
 
34
 */
 
35
        public void
 
36
put_line()
 
37
{
 
38
        register int c;
 
39
        register int i;
 
40
        int a;
 
41
        int curr_attr;
 
42
 
 
43
        if (ABORT_SIGS())
 
44
        {
 
45
                /*
 
46
                 * Don't output if a signal is pending.
 
47
                 */
 
48
                screen_trashed = 1;
 
49
                return;
 
50
        }
 
51
 
 
52
        curr_attr = AT_NORMAL;
 
53
 
 
54
        for (i = 0;  (c = gline(i, &a)) != '\0';  i++)
 
55
        {
 
56
                if (a != curr_attr)
 
57
                {
 
58
                        /*
 
59
                         * Changing attributes.
 
60
                         * Display the exit sequence for the old attribute
 
61
                         * and the enter sequence for the new one.
 
62
                         */
 
63
                        switch (curr_attr)
 
64
                        {
 
65
                        case AT_UNDERLINE:      ul_exit();      break;
 
66
                        case AT_BOLD:           bo_exit();      break;
 
67
                        case AT_BLINK:          bl_exit();      break;
 
68
                        case AT_STANDOUT:       so_exit();      break;
 
69
                        }
 
70
                        switch (a)
 
71
                        {
 
72
                        case AT_UNDERLINE:      ul_enter();     break;
 
73
                        case AT_BOLD:           bo_enter();     break;
 
74
                        case AT_BLINK:          bl_enter();     break;
 
75
                        case AT_STANDOUT:       so_enter();     break;
 
76
                        }
 
77
                        curr_attr = a;
 
78
                }
 
79
                if (curr_attr == AT_INVIS)
 
80
                        continue;
 
81
                if (c == '\b')
 
82
                        putbs();
 
83
                else
 
84
                        putchr(c);
 
85
        }
 
86
 
 
87
        switch (curr_attr)
 
88
        {
 
89
        case AT_UNDERLINE:      ul_exit();      break;
 
90
        case AT_BOLD:           bo_exit();      break;
 
91
        case AT_BLINK:          bl_exit();      break;
 
92
        case AT_STANDOUT:       so_exit();      break;
 
93
        }
 
94
        final_attr = curr_attr;
 
95
}
 
96
 
 
97
static char obuf[OUTBUF_SIZE];
 
98
static char *ob = obuf;
 
99
 
 
100
/*
 
101
 * Flush buffered output.
 
102
 *
 
103
 * If we haven't displayed any file data yet,
 
104
 * output messages on error output (file descriptor 2),
 
105
 * otherwise output on standard output (file descriptor 1).
 
106
 *
 
107
 * This has the desirable effect of producing all
 
108
 * error messages on error output if standard output
 
109
 * is directed to a file.  It also does the same if
 
110
 * we never produce any real output; for example, if
 
111
 * the input file(s) cannot be opened.  If we do
 
112
 * eventually produce output, code in edit() makes
 
113
 * sure these messages can be seen before they are
 
114
 * overwritten or scrolled away.
 
115
 */
 
116
        public void
 
117
flush()
 
118
{
 
119
        register int n;
 
120
        register int fd;
 
121
 
 
122
        n = ob - obuf;
 
123
        if (n == 0)
 
124
                return;
 
125
#if MSDOS_COMPILER==WIN32C
 
126
        if (is_tty && any_display)
 
127
        {
 
128
                char *op;
 
129
                DWORD nwritten = 0;
 
130
                CONSOLE_SCREEN_BUFFER_INFO scr;
 
131
                int row;
 
132
                int col;
 
133
                int olen;
 
134
                extern HANDLE con_out;
 
135
 
 
136
                olen = ob - obuf;
 
137
                /*
 
138
                 * There is a bug in Win32 WriteConsole() if we're
 
139
                 * writing in the last cell with a different color.
 
140
                 * To avoid color problems in the bottom line,
 
141
                 * we scroll the screen manually, before writing.
 
142
                 */
 
143
                GetConsoleScreenBufferInfo(con_out, &scr);
 
144
                col = scr.dwCursorPosition.X;
 
145
                row = scr.dwCursorPosition.Y;
 
146
                for (op = obuf;  op < obuf + olen;  op++)
 
147
                {
 
148
                        if (*op == '\n')
 
149
                        {
 
150
                                col = 0;
 
151
                                row++;
 
152
                        } else
 
153
                        {
 
154
                                col++;
 
155
                                if (col >= sc_width)
 
156
                                {
 
157
                                        col = 0;
 
158
                                        row++;
 
159
                                }
 
160
                        }
 
161
                }
 
162
                if (row > scr.srWindow.Bottom)
 
163
                        win32_scroll_up(row - scr.srWindow.Bottom);
 
164
                WriteConsole(con_out, obuf, olen, &nwritten, NULL);
 
165
                ob = obuf;
 
166
                return;
 
167
        }
 
168
#else
 
169
#if MSDOS_COMPILER==MSOFTC
 
170
        if (is_tty && any_display)
 
171
        {
 
172
                *ob = '\0';
 
173
                _outtext(obuf);
 
174
                ob = obuf;
 
175
                return;
 
176
        }
 
177
#else
 
178
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
 
179
        if (is_tty && any_display)
 
180
        {
 
181
                *ob = '\0';
 
182
                cputs(obuf);
 
183
                ob = obuf;
 
184
                return;
 
185
        }
 
186
#endif
 
187
#endif
 
188
#endif
 
189
        fd = (any_display) ? 1 : 2;
 
190
        if (write(fd, obuf, n) != n)
 
191
                screen_trashed = 1;
 
192
        ob = obuf;
 
193
}
 
194
 
 
195
/*
 
196
 * Output a character.
 
197
 */
 
198
        public int
 
199
putchr(c)
 
200
        int c;
 
201
{
 
202
        if (need_clr)
 
203
        {
 
204
                need_clr = 0;
 
205
                clear_bot();
 
206
        }
 
207
#if MSDOS_COMPILER
 
208
        if (c == '\n' && is_tty)
 
209
        {
 
210
                /* remove_top(1); */
 
211
                putchr('\r');
 
212
        }
 
213
#else
 
214
#ifdef _OSK
 
215
        if (c == '\n' && is_tty)  /* In OS-9, '\n' == 0x0D */
 
216
                putchr(0x0A);
 
217
#endif
 
218
#endif
 
219
        /*
 
220
         * Some versions of flush() write to *ob, so we must flush
 
221
         * when we are still one char from the end of obuf.
 
222
         */
 
223
        if (ob >= &obuf[sizeof(obuf)-1])
 
224
                flush();
 
225
        *ob++ = c;
 
226
        return (c);
 
227
}
 
228
 
 
229
/*
 
230
 * Output a string.
 
231
 */
 
232
        public void
 
233
putstr(s)
 
234
        register char *s;
 
235
{
 
236
        while (*s != '\0')
 
237
                putchr(*s++);
 
238
}
 
239
 
 
240
 
 
241
/*
 
242
 * Output an integer in a given radix.
 
243
 */
 
244
        static int
 
245
iprintnum(num, radix)
 
246
        int num;
 
247
        int radix;
 
248
{
 
249
        register char *s;
 
250
        int r;
 
251
        int neg;
 
252
        char buf[INT_STRLEN_BOUND(num)];
 
253
 
 
254
        neg = (num < 0);
 
255
        if (neg)
 
256
                num = -num;
 
257
 
 
258
        s = buf;
 
259
        do
 
260
        {
 
261
                *s++ = (num % radix) + '0';
 
262
        } while ((num /= radix) != 0);
 
263
 
 
264
        if (neg)
 
265
                *s++ = '-';
 
266
        r = s - buf;
 
267
 
 
268
        while (s > buf)
 
269
                putchr(*--s);
 
270
        return (r);
 
271
}
 
272
 
 
273
/*
 
274
 * This function implements printf-like functionality
 
275
 * using a more portable argument list mechanism than printf's.
 
276
 */
 
277
        static int
 
278
less_printf(fmt, parg)
 
279
        register char *fmt;
 
280
        PARG *parg;
 
281
{
 
282
        register char *s;
 
283
        register int n;
 
284
        register int col;
 
285
 
 
286
        col = 0;
 
287
        while (*fmt != '\0')
 
288
        {
 
289
                if (*fmt != '%')
 
290
                {
 
291
                        putchr(*fmt++);
 
292
                        col++;
 
293
                } else
 
294
                {
 
295
                        ++fmt;
 
296
                        switch (*fmt++) {
 
297
                        case 's':
 
298
                                s = parg->p_string;
 
299
                                parg++;
 
300
                                while (*s != '\0')
 
301
                                {
 
302
                                        putchr(*s++);
 
303
                                        col++;
 
304
                                }
 
305
                                break;
 
306
                        case 'd':
 
307
                                n = parg->p_int;
 
308
                                parg++;
 
309
                                col += iprintnum(n, 10);
 
310
                                break;
 
311
                        }
 
312
                }
 
313
        }
 
314
        return (col);
 
315
}
 
316
 
 
317
/*
 
318
 * Get a RETURN.
 
319
 * If some other non-trivial char is pressed, unget it, so it will
 
320
 * become the next command.
 
321
 */
 
322
        public void
 
323
get_return()
 
324
{
 
325
        int c;
 
326
 
 
327
#if ONLY_RETURN
 
328
        while ((c = getchr()) != '\n' && c != '\r')
 
329
                bell();
 
330
#else
 
331
        c = getchr();
 
332
        if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
 
333
                ungetcc(c);
 
334
#endif
 
335
}
 
336
 
 
337
/*
 
338
 * Output a message in the lower left corner of the screen
 
339
 * and wait for carriage return.
 
340
 */
 
341
        public void
 
342
error(fmt, parg)
 
343
        char *fmt;
 
344
        PARG *parg;
 
345
{
 
346
        int col = 0;
 
347
        static char return_to_continue[] = "  (press RETURN)";
 
348
 
 
349
        errmsgs++;
 
350
 
 
351
        if (any_display && is_tty)
 
352
        {
 
353
                clear_bot();
 
354
                so_enter();
 
355
                col += so_s_width;
 
356
        }
 
357
 
 
358
        col += less_printf(fmt, parg);
 
359
 
 
360
        if (!(any_display && is_tty))
 
361
        {
 
362
                putchr('\n');
 
363
                return;
 
364
        }
 
365
 
 
366
        putstr(return_to_continue);
 
367
        so_exit();
 
368
        col += sizeof(return_to_continue) + so_e_width;
 
369
 
 
370
        get_return();
 
371
        lower_left();
 
372
 
 
373
        if (col >= sc_width)
 
374
                /*
 
375
                 * Printing the message has probably scrolled the screen.
 
376
                 * {{ Unless the terminal doesn't have auto margins,
 
377
                 *    in which case we just hammered on the right margin. }}
 
378
                 */
 
379
                screen_trashed = 1;
 
380
 
 
381
        flush();
 
382
}
 
383
 
 
384
static char intr_to_abort[] = "... (interrupt to abort)";
 
385
 
 
386
/*
 
387
 * Output a message in the lower left corner of the screen
 
388
 * and don't wait for carriage return.
 
389
 * Usually used to warn that we are beginning a potentially
 
390
 * time-consuming operation.
 
391
 */
 
392
        public void
 
393
ierror(fmt, parg)
 
394
        char *fmt;
 
395
        PARG *parg;
 
396
{
 
397
        clear_bot();
 
398
        so_enter();
 
399
        (void) less_printf(fmt, parg);
 
400
        putstr(intr_to_abort);
 
401
        so_exit();
 
402
        flush();
 
403
        need_clr = 1;
 
404
}
 
405
 
 
406
/*
 
407
 * Output a message in the lower left corner of the screen
 
408
 * and return a single-character response.
 
409
 */
 
410
        public int
 
411
query(fmt, parg)
 
412
        char *fmt;
 
413
        PARG *parg;
 
414
{
 
415
        register int c;
 
416
        int col = 0;
 
417
 
 
418
        if (any_display && is_tty)
 
419
                clear_bot();
 
420
 
 
421
        (void) less_printf(fmt, parg);
 
422
        c = getchr();
 
423
 
 
424
        if (!(any_display && is_tty))
 
425
        {
 
426
                putchr('\n');
 
427
                return (c);
 
428
        }
 
429
 
 
430
        lower_left();
 
431
        if (col >= sc_width)
 
432
                screen_trashed = 1;
 
433
        flush();
 
434
 
 
435
        return (c);
 
436
}