Subversion Repositories SvarDOS

Rev

Rev 1275 | Rev 1282 | Go to most recent revision | Details | Compare with Previous | 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 */
1276 mateusz.vi 140
  if (db->xoffset > db->cursor->len) db->xoffset = db->cursor->len - 1;
1275 mateusz.vi 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
 
1276 mateusz.vi 146
static void cursor_down(struct linedb *db, unsigned char *cursorposy, unsigned char screenh) {
147
  if (db->cursor->next != NULL) {
148
    db->cursor = db->cursor->next;
149
    if (*cursorposy < screenh - 2) {
150
      *cursorposy += 1;
151
    } else {
152
      db->topscreen = db->topscreen->next;
153
    }
154
  }
155
}
156
 
157
 
158
static void cursor_home(struct linedb *db, unsigned char *cursorposx) {
159
  *cursorposx = 0;
160
  db->xoffset = 0;
161
}
162
 
163
 
1275 mateusz.vi 164
int main(int argc, char **argv) {
165
  FILE *fd;
166
  const char *fname = NULL;
167
  char buff[1024];
168
  struct linedb db;
169
  unsigned char screenw = 0, screenh = 0;
170
  unsigned char cursorposx = 0, cursorposy = 0;
171
 
172
  bzero(&db, sizeof(db));
173
 
174
  if ((argc != 2) || (argv[1][0] == '/')) {
175
    mdr_coutraw_puts("usage: sved file.txt");
176
    return(0);
177
  }
178
 
179
  fname = argv[1];
180
 
181
  printf("Loading %s...", fname);
182
  mdr_coutraw_puts("");
183
 
184
  fd = fopen(fname, "rb");
185
  if (fd == NULL) {
186
    printf("ERROR: failed to open file %s", fname);
187
    mdr_coutraw_puts("");
188
    return(1);
189
  }
190
 
191
  while (fgets(buff, sizeof(buff), fd) != NULL) {
192
    line_add(&db, buff);
193
  }
194
  /* add an empty line at end if not present already */
195
  if (db.cursor->len != 0) line_add(&db, "");
196
 
197
  fclose(fd);
198
 
199
  if (mdr_cout_init(&screenw, &screenh)) load_colorscheme();
200
  ui_basic(screenw, screenh, fname);
201
 
202
  db_rewind(&db);
203
 
204
  for (;;) {
205
    int k;
206
 
207
    check_cursor_not_after_eol(&db, &cursorposx);
208
    mdr_cout_locate(cursorposy, cursorposx);
209
 
210
    ui_refresh(&db, screenw, screenh);
211
 
212
    k = keyb_getkey();
213
    if (k == 0x150) { /* down */
1276 mateusz.vi 214
      cursor_down(&db, &cursorposy, screenh);
1275 mateusz.vi 215
 
216
    } else if (k == 0x148) { /* up */
217
      cursor_up(&db, &cursorposy);
218
 
219
    } else if (k == 0x14D) { /* right */
220
      if (db.cursor->len > db.xoffset + cursorposx) {
221
        if (cursorposx < screenw - 2) {
222
          cursorposx++;
223
        } else {
224
          db.xoffset++;
225
        }
1276 mateusz.vi 226
      } else {
227
        cursor_down(&db, &cursorposy, screenh);
228
        cursor_home(&db, &cursorposx);
1275 mateusz.vi 229
      }
230
 
231
    } else if (k == 0x14B) { /* left */
232
      if (cursorposx > 0) {
233
        cursorposx--;
234
      } else if (db.xoffset > 0) {
235
        db.xoffset--;
1276 mateusz.vi 236
      } else if (db.cursor->prev != NULL) { /* jump to end of line above */
1275 mateusz.vi 237
        cursor_up(&db, &cursorposy);
238
        cursor_eol(&db, &cursorposx, screenw);
239
      }
240
 
241
    } else if (k == 0x1B) { /* ESC */
242
      break;
243
 
244
    } else {
245
      printf("UNHANDLED KEY 0x%02X", k);
246
      keyb_getkey();
247
      break;
248
    }
249
  }
250
 
251
  mdr_cout_close();
252
 
253
  /* TODO free memory */
254
 
255
  return(0);
256
}