File: ansi.c

package info (click to toggle)
arj 3.10.22-29
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,964 kB
  • sloc: ansic: 33,002; makefile: 2,014; sh: 1,587; asm: 436
file content (272 lines) | stat: -rw-r--r-- 6,490 bytes parent folder | download | duplicates (13)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
 * $Id: ansi.c,v 1.1.1.1 2002/03/27 23:25:18 andrew_belov Exp $
 * ---------------------------------------------------------------------------
 * Routines to display ANSI  comments are  located here. Not all  routines are
 * supported - first of all, this restriction applies  to graphic commands. It
 * has to be noted that the code  comes from  some PASCAL snippet - therefore,
 * arrays are 1-based.
 *
 */

#include "arj.h"

DEBUGHDR(__FILE__)                      /* Debug information block */

#define TEXTCOLOR_MASK          0x07    /* Basic colors */
#define TEXTFORE_MASK           0x0F    /* Text */
#define TESTBACK_MASK           0xF0    /* Background */
#define TEXT_BRIGHT                8    /* Bright text bit */
#define TEXT_BLINK              0x80    /* Blinking text bit */

#ifndef DIRECT_TO_ANSI

static char ansi_initialized=0;         /* 1 once init_ansi() is called */
static char ansi_commands[]="HFABCDNJMSUK";

static int esc_found;                   /* 1 if the last character was ESC */
static int ansi_seq_found;              /* 1 if a valid sequence is detected */
static char ansi_ptr;                   /* Offset within internal buffer */
static char ansi_buf[22];               /* Internal buffer */
static int ansi_bright;                 /* 1 will enable bright characters */
static int ansi_blink;                  /* 1 makes the blinking or bright
                                           background (0x80) */
static unsigned char ansi_saved_x;      /* Saved X coordinate */
static unsigned char ansi_saved_y;      /* Saved Y coordinate */

/* Initializes ANSI display structures */

static void init_ansi()
{
 memset(ansi_buf, 32, sizeof(ansi_buf));
 ansi_bright=ansi_blink=0;
 esc_found=0;
 ansi_seq_found=0;
 ansi_ptr=0;
 ansi_saved_x=ansi_saved_y=1;
}

/* Processes the ANSI sequence stored in the buffer */

static void process_ansi_cmd()
{
 char pad_buf[20];
 char cur_pos;
 char tmp_pos;                          /* Temporary pointer */
 char dec_pos;
 char param;                            /* Current decimal position */
 char tmp_color=0;
 char tmp_back;

 param=0;
 dec_pos=1;
 pad_buf[1]=pad_buf[2]=1;
 for(cur_pos=1; cur_pos!=ansi_ptr; cur_pos++)
 {
  if(param==0)                          /* Parameters start at 1 */
   param++;
  if(isdigit((int)ansi_buf[cur_pos])&&dec_pos<3)
  {
   pad_buf[param]=(dec_pos==1)?ansi_buf[cur_pos]-'0':pad_buf[param]*10+ansi_buf[cur_pos]-'0';
   dec_pos++;
  }
  else
  {
   if(ansi_buf[cur_pos]==ANSI_DELIMITER)
   {
    if(dec_pos==1)
     pad_buf[param]=1;
    param++;
    dec_pos=1;
   }
  }
 }
 /* The parameters are referenced as (X; Y) */
 switch(ansi_buf[ansi_ptr])
 {
  /* Move the cursor X rows up */
  case 'A':
   gotoxy(wherex(), wherey()-pad_buf[1]);
   break;
  /* Move the cursor X rows down */
  case 'B':
   gotoxy(wherex(), wherey()+pad_buf[1]);
   break;
  /* Move the cursor X columns left */
  case 'C':
   gotoxy(wherex()+pad_buf[1], wherey());
   break;
  /* Move the cursor X columns right */
  case 'D':
   gotoxy(wherex()-pad_buf[1], wherey());
   break;
  /* Set the cursor position to (Y; X) */
  case 'F':
  case 'H':
   gotoxy(pad_buf[2], pad_buf[1]);
   break;
  /* Clear the screen (quite incorrect, since only ^[[2J does it) */
  case 'J':
   clrscr();
   break;
  /* Clear all character from current position to end of line */
  case 'K':
   clreol();
   break;
  /* Set the text attributes */
  case 'M':
   for(tmp_pos=1; tmp_pos<=param; tmp_pos++)
   {
    switch(pad_buf[tmp_pos])
    {
     /* Set the default attributes */
     case 0:
      textcolor(7);
      textbackground(0);
      ansi_bright=ansi_blink=0;
      break;
     /* Set the bright mode on */
     case 1:
      ansi_bright=1;
      textcolor(getcurattr()&TEXTFORE_MASK|TEXT_BRIGHT);
      break;
     /* Set the blinking mode on */
     case 5:
      ansi_blink=1;
      textattr(getcurattr()|TEXT_BLINK);
      break;
     /* Set the inverse video on. The code in original ARJ is a bit incorrect
        here, because it swaps the foreground and background colors. */
     case 7:
      textattr(0x70);
      break;
     /* Make the text invisible by setting the foreground color the same
        as the background color. */
     case 8:
      tmp_back=(getcurattr()>>4)|TEXTCOLOR_MASK;
      textcolor(tmp_back);
      break;
     /* Set the text foreground color */
     case 30:
     case 31:
     case 32:
     case 33:
     case 34:
     case 35:
     case 36:
     case 37:
      switch(pad_buf[tmp_pos])
      {
       case 30:
        tmp_color=0;
        break;
       case 31:
        tmp_color=4;
        break;
       case 32:
        tmp_color=2;
        break;
       case 33:
        tmp_color=6;
        break;
       case 34:
        tmp_color=1;
        break;
       case 35:
        tmp_color=5;
        break;
       case 36:
        tmp_color=3;
        break;
       case 37:
        tmp_color=7;
        break;
      }
      if(ansi_bright)
       tmp_color|=TEXT_BRIGHT;
      if(ansi_blink)
       tmp_color|=TEXT_BLINK;
      textcolor(tmp_color);
      break;
     /* Set the background colors */
     case 40:
      textbackground(0);
      break;
     case 41:
      textbackground(4);
      break;
     case 42:
      textbackground(2);
      break;
     case 43:
      textbackground(6);
      break;
     case 44:
      textbackground(1);
      break;
     case 45:
      textbackground(5);
      break;
     case 46:
      textbackground(3);
      break;
     case 47:
      textbackground(7);
      break;
    }
   }
   break;
  /* Save the current cursor coordinates */
  case 'S':
   ansi_saved_x=(unsigned char)wherex();
   ansi_saved_y=(unsigned char)wherey();
   break;
  /* Restore the saved coordinates */
  case 'U':
   gotoxy((int)ansi_saved_x, (int)ansi_saved_y);
   break;
 }
}

/* Accumulates given characters and displays ANSI sequences once they're
   formed */

void display_ansi(char c)
{
 if(!ansi_initialized)
 {
  init_ansi();
  ansi_initialized=1;
 }
 if(c==ANSI_ESC)
 {
  esc_found=1;
  return;
 }
 if(c==ANSI_BRACKET&&esc_found)
 {
  ansi_seq_found=1;
  return;
 }
 if(esc_found&&ansi_seq_found)
 {
  ansi_buf[++ansi_ptr]=toupper(c);
  if(ansi_ptr<sizeof(ansi_buf))
  {
   if(strchr(ansi_commands, toupper(c))!=NULL)
   {
    process_ansi_cmd();
    esc_found=ansi_seq_found=0;
    ansi_ptr=0;
   }
  }
  else
  {
   esc_found=ansi_seq_found=0;
   ansi_ptr=0;
  }
 }
 else
  wputch((int)c);
}

#endif /* !defined(DIRECT_TO_ANSI) */