Subversion Repositories SvarDOS

Rev

Rev 1276 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1275 mateusz.vi 1
/* */
2
 
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
 
7
#include "mdr\cout.h"
8
#include "mdr\keyb.h"
9
 
10
#define COL_TXT        0
11
#define COL_STATUSBAR1 1
12
#define COL_STATUSBAR2 2
13
#define COL_SCROLLBAR  3
14
/* preload the mono scheme (to be overloaded at runtime if color adapter present) */
15
static unsigned char scheme[] = {0x07, 0x70, 0x70, 0x70};
16
 
17
#define SCROLL_CURSOR 0xB1
18
 
19
 
20
struct line {
21
  struct line *prev;
22
  struct line *next;
23
  unsigned short len;
24
  char payload[1];
25
};
26
 
27
struct linedb {
28
  struct line *topscreen;
29
  struct line *cursor;
30
  unsigned short xoffset;
31
};
32
 
33
 
34
void line_add(struct linedb *db, const char *line) {
35
  unsigned short slen = strlen(line);
36
  struct line *l;
37
 
38
  /* trim out CR/LF line endings */
39
  if ((slen >= 2) && (line[slen - 2] == '\r')) {
40
    slen -= 2;
41
  } else if ((slen >= 1) && (line[slen - 1] == '\n')) {
42
    slen--;
43
  }
44
 
45
  l =  calloc(1, sizeof(struct line) + slen + 1);
46
  l->prev = db->cursor;
47
  if (db->cursor) {
48
    l->next = db->cursor->next;
49
    db->cursor->next = l;
50
    l->next->prev = l;
51
  }
52
  db->cursor = l;
53
  memcpy(l->payload, line, slen);
54
  l->len = slen;
55
}
56
 
57
 
58
void db_rewind(struct linedb *db) {
59
  if (db->cursor == NULL) return;
60
  while (db->cursor->prev) db->cursor = db->cursor->prev;
61
  db->topscreen = db->cursor;
62
}
63
 
64
 
65
void load_colorscheme(void) {
66
  scheme[COL_TXT] = 0x17;
67
  scheme[COL_STATUSBAR1] = 0x70;
68
  scheme[COL_STATUSBAR2] = 0x78;
69
  scheme[COL_SCROLLBAR] = 0x70;
70
}
71
 
72
 
73
void ui_basic(unsigned char screenw, unsigned char screenh, const char *fname) {
74
  unsigned char i;
75
  const char *s = "HELP";
76
  unsigned char helpcol = screenw - (strlen(s) + 4);
77
 
78
  /* clear screen */
79
  mdr_cout_cls(scheme[COL_TXT]);
80
 
81
  /* status bar */
82
  for (i = 0; i < helpcol; i++) {
83
    mdr_cout_char(screenh - 1, i, *fname, scheme[COL_STATUSBAR1]);
84
    if (*fname != 0) fname++;
85
  }
86
  mdr_cout_str(screenh - 1, helpcol, " F1=", scheme[COL_STATUSBAR2], 40);
87
  mdr_cout_str(screenh - 1, helpcol + 4, s, scheme[COL_STATUSBAR2], 40);
88
 
89
  /* scroll bar */
90
  for (i = 0; i < (screenh - 1); i++) {
91
    mdr_cout_char(i, screenw - 1, SCROLL_CURSOR, scheme[COL_SCROLLBAR]);
92
  }
93
}
94
 
95
 
96
void ui_refresh(const struct linedb *db, unsigned char screenw, unsigned char screenh) {
97
  unsigned char y = 0;
98
  unsigned char len;
99
  struct line *l;
100
 
101
  for (l = db->topscreen; l != NULL; l = l->next) {
102
    if (db->xoffset < l->len) {
103
      len = mdr_cout_str(y, 0, l->payload + db->xoffset, scheme[COL_TXT], screenw - 1);
104
    } else {
105
      len = 0;
106
    }
107
    while (len < screenw - 1) mdr_cout_char(y, len++, ' ', scheme[COL_TXT]);
108
    if (y == screenh - 2) break;
109
    y++;
110
  }
111
}
112
 
113
 
114
static void check_cursor_not_after_eol(struct linedb *db, unsigned char *cursorpos) {
115
  if (db->xoffset + *cursorpos <= db->cursor->len) return;
116
 
117
  if (db->cursor->len < db->xoffset) {
118
    *cursorpos = 0;
119
    db->xoffset = db->cursor->len;
120
  } else {
121
    *cursorpos = db->cursor->len - db->xoffset;
122
  }
123
}
124
 
125
 
126
static void cursor_up(struct linedb *db, unsigned char *cursorposy) {
127
  if (db->cursor->prev != NULL) {
128
    db->cursor = db->cursor->prev;
129
    if (*cursorposy == 0) {
130
      db->topscreen = db->cursor;
131
    } else {
132
      *cursorposy -= 1;
133
    }
134
  }
135
}
136
 
137
 
138
static void cursor_eol(struct linedb *db, unsigned char *cursorposx, unsigned char screenw) {
139
  /* adjust xoffset to make sure eol is visible on screen */
140
  if (db->xoffset >= db->cursor->len) db->xoffset = db->cursor->len - 1;
141
  if (db->xoffset + screenw - 1 <= db->cursor->len) db->xoffset = db->cursor->len - screenw + 2;
142
  *cursorposx = db->cursor->len - db->xoffset;
143
}
144
 
145
 
146
int main(int argc, char **argv) {
147
  FILE *fd;
148
  const char *fname = NULL;
149
  char buff[1024];
150
  struct linedb db;
151
  unsigned char screenw = 0, screenh = 0;
152
  unsigned char cursorposx = 0, cursorposy = 0;
153
 
154
  bzero(&db, sizeof(db));
155
 
156
  if ((argc != 2) || (argv[1][0] == '/')) {
157
    mdr_coutraw_puts("usage: sved file.txt");
158
    return(0);
159
  }
160
 
161
  fname = argv[1];
162
 
163
  printf("Loading %s...", fname);
164
  mdr_coutraw_puts("");
165
 
166
  fd = fopen(fname, "rb");
167
  if (fd == NULL) {
168
    printf("ERROR: failed to open file %s", fname);
169
    mdr_coutraw_puts("");
170
    return(1);
171
  }
172
 
173
  while (fgets(buff, sizeof(buff), fd) != NULL) {
174
    line_add(&db, buff);
175
  }
176
  /* add an empty line at end if not present already */
177
  if (db.cursor->len != 0) line_add(&db, "");
178
 
179
  fclose(fd);
180
 
181
  if (mdr_cout_init(&screenw, &screenh)) load_colorscheme();
182
  ui_basic(screenw, screenh, fname);
183
 
184
  db_rewind(&db);
185
 
186
  for (;;) {
187
    int k;
188
 
189
    check_cursor_not_after_eol(&db, &cursorposx);
190
    mdr_cout_locate(cursorposy, cursorposx);
191
 
192
    ui_refresh(&db, screenw, screenh);
193
 
194
    k = keyb_getkey();
195
    if (k == 0x150) { /* down */
196
      if (db.cursor->next != NULL) {
197
        db.cursor = db.cursor->next;
198
        if (cursorposy < screenh - 2) {
199
          cursorposy++;
200
        } else {
201
          db.topscreen = db.topscreen->next;
202
        }
203
      }
204
 
205
    } else if (k == 0x148) { /* up */
206
      cursor_up(&db, &cursorposy);
207
 
208
    } else if (k == 0x14D) { /* right */
209
      if (db.cursor->len > db.xoffset + cursorposx) {
210
        if (cursorposx < screenw - 2) {
211
          cursorposx++;
212
        } else {
213
          db.xoffset++;
214
        }
215
      }
216
 
217
    } else if (k == 0x14B) { /* left */
218
      if (cursorposx > 0) {
219
        cursorposx--;
220
      } else if (db.xoffset > 0) {
221
        db.xoffset--;
222
      } else {
223
        cursor_up(&db, &cursorposy);
224
        cursor_eol(&db, &cursorposx, screenw);
225
      }
226
 
227
    } else if (k == 0x1B) { /* ESC */
228
      break;
229
 
230
    } else {
231
      printf("UNHANDLED KEY 0x%02X", k);
232
      keyb_getkey();
233
      break;
234
    }
235
  }
236
 
237
  mdr_cout_close();
238
 
239
  /* TODO free memory */
240
 
241
  return(0);
242
}