Skip to content

Commit a9a3a15

Browse files
committed
[CPP] Multiline input in LOGO
1 parent 8439e96 commit a9a3a15

File tree

2 files changed

+89
-25
lines changed

2 files changed

+89
-25
lines changed

src/usr/include/string.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ inline bool operator==(const CharT* a, const std::basic_string<CharT> &b) { retu
8181
template<typename CharT>
8282
inline bool operator==(const std::basic_string<CharT> &a, const std::basic_string<CharT> &b) { return std::strcmp(a.c_str(), b.c_str()) == 0; }
8383

84+
template<typename CharT>
85+
inline bool operator!=(const std::basic_string<CharT> &a, const CharT* b) { return !operator==(a,b); }
86+
template<typename CharT>
87+
inline bool operator!=(const CharT* a, const std::basic_string<CharT> &b) { return !operator==(a,b); }
88+
template<typename CharT>
89+
inline bool operator!=(const std::basic_string<CharT> &a, const std::basic_string<CharT> &b) { return !operator==(a,b); }
90+
8491
template<typename CharT>
8592
inline bool operator<(const std::basic_string<CharT> &a, const CharT* b) { return std::strcmp(a.c_str(), b) < 0; }
8693
template<typename CharT>

src/usr/local/src/logo.cpp

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ const int BUSY_WAIT_FRAMECOUNTER = 2e7;
1111

1212
const int WINDOW_HEIGHT = GRAPHICS_MAX_HEIGHT;
1313
const int WINDOW_WIDTH = GRAPHICS_MAX_WIDTH;
14-
const int INTERPRETER_HEIGHT = 16*4;
1514

1615
char message_buffer[320];
1716

@@ -52,6 +51,9 @@ class Display {
5251
double angle; // in radians
5352
bool pen_active; // true implies draw when pen moves
5453
bool turtle_visiblity;
54+
55+
// repeat command internals
56+
std::vector<std::pair<std::size_t, int> > repeat_stack; // (start, count)
5557
public:
5658
Display(int height) : height(height),
5759
current(WINDOW_WIDTH / 2, height / 2),
@@ -107,6 +109,35 @@ class Display {
107109
}
108110

109111
int command_handler(std::string &cmd, std::string &input, std::size_t &start) {
112+
if (cmd.empty()) {
113+
// no more command left
114+
return 0;
115+
}
116+
117+
if (cmd == "repeat") {
118+
std::string arg0=parse_next_token(input, start);
119+
std::string arg1=parse_next_token(input, start);
120+
if (arg0.empty()) return 2;
121+
if (arg1 != "[" ) return 3;
122+
int count = std::atoi(arg0.c_str());
123+
if (count > 0) {
124+
repeat_stack.push_back(std::make_pair(start, count-1));
125+
}
126+
return 0;
127+
}
128+
if (cmd == "]") {
129+
if (repeat_stack.empty()) return 2;
130+
if (repeat_stack.back().second == 0) {
131+
// repeat over
132+
repeat_stack.pop_back();
133+
return 0;
134+
}
135+
repeat_stack.back().second--;
136+
start = repeat_stack.back().first; // repeat again
137+
return 0;
138+
}
139+
140+
110141
if (cmd == "fd" || cmd == "forward") {
111142
std::string arg=parse_next_token(input, start);
112143
if (arg.empty()) return 2;
@@ -163,7 +194,7 @@ class Display {
163194
if (cmd == "exit") {
164195
std::exit(0);
165196
}
166-
return 0;
197+
return 10;
167198
}
168199

169200
std::string parse_next_token(std::string &input, std::size_t &start) {
@@ -184,6 +215,7 @@ class Display {
184215

185216
int parse(std::string input) {
186217
std::size_t start = 0;
218+
repeat_stack.clear();
187219
while (1) {
188220
std::string cmd = parse_next_token(input, start);
189221
if (cmd.empty()) break;
@@ -192,6 +224,9 @@ class Display {
192224
return err;
193225
}
194226
}
227+
if (!repeat_stack.empty()) {
228+
return 1; // all repeat must be completed
229+
}
195230
return 0;
196231
}
197232

@@ -228,15 +263,20 @@ class Display {
228263
};
229264

230265
class Console {
231-
const int line_count = 4;
232-
std::vector<std::string> data;
266+
const int line_count = 3;
267+
const int LINE_STATUS = 0;
268+
std::string status_err;
269+
std::string status_loc;
270+
std::string input_line;
233271
int y_offset;
234272
int text_height;
273+
int text_width;
235274
const int border = 5;
236275

237276
public:
238-
Console(): data(line_count, "") {
277+
Console(): input_line("") {
239278
text_height = std::graphics::textheight(".");
279+
text_width = std::graphics::textwidth(".");
240280
y_offset = WINDOW_HEIGHT-text_height*line_count-2*border;
241281
}
242282

@@ -246,58 +286,75 @@ class Console {
246286

247287
std::string read() {
248288
int index = 0;
249-
std::string &input = data[index];
250289
char ch;
251290
while(1) {
252291
ch = std::getch();
253292
if(ch=='\n') {
254-
std::string out = input; // copy
255-
input.clear();
293+
std::string out = input_line; // copy
294+
input_line.clear();
256295
draw();
257296
return out;
258297
}
259-
input+=ch;
298+
input_line+=ch;
260299
draw();
261300
}
262301
}
263302

264303
void set_err(int err) {
265-
int index = 1; // error line
266304
if(err==0) {
267-
data[index].clear();
305+
status_err.clear();
268306
} else {
269-
data[index] = "error!";
307+
status_err = "error!";
270308
}
271309
draw();
272310
}
273311

274-
void update_log(Display &display) {
312+
void update_status(Display &display) {
275313
int current_x = display.get_x();
276314
int current_y = display.get_y();
277315
int angle_deg = std::round(display.get_angle()*180/M_PI);
278316

279-
int index = 2; // current location
280-
auto &log = data[index];
281-
log = "loc: ";
317+
status_loc = "loc: ";
282318
char buffer[16];
283319
std::itoa(current_x, buffer, 10);
284-
log += buffer;
285-
log += ',';
320+
status_loc += buffer;
321+
status_loc += ',';
286322
std::itoa(current_y, buffer, 10);
287-
log += buffer;
323+
status_loc += buffer;
288324

289325
std::itoa(angle_deg, buffer, 10);
290-
log += " dir: ";
291-
log += buffer;
292-
log += " deg";
326+
status_loc += " dir: ";
327+
status_loc += buffer;
328+
status_loc += " deg ";
293329
}
294330

295331
void draw() {
296332
std::graphics::setcolor(YELLOW);
297333
std::graphics::bar(0, y_offset, WINDOW_WIDTH-1, WINDOW_HEIGHT-1);
298334
std::graphics::setcolor(BLACK);
335+
{
336+
int line_number = 0; // loc, angle, err
337+
int _x = border;
338+
int _y = y_offset+line_number*text_height;
339+
_x += std::graphics::outtextxy(_x, _y, status_loc.c_str());
340+
std::graphics::outtextxy(_x, _y, status_err.c_str());
341+
}
342+
const int char_per_line = (WINDOW_WIDTH-2*border)/text_width;
299343
for (std::size_t i = 0; i < line_count; i++) {
300-
std::graphics::outtextxy(border, y_offset+i*text_height+border, data[i].c_str());
344+
int _y = y_offset+(i+1)*text_height;
345+
int _x = border;
346+
int str_start = char_per_line*i;
347+
int str_end = char_per_line*(i+1); // excluding
348+
if (str_start >= input_line.length()) break;
349+
char shelve_end = '\0';
350+
if (str_end < input_line.length()) {
351+
shelve_end = input_line[str_end];
352+
input_line[str_end] = '\0';
353+
}
354+
std::graphics::outtextxy(_x, _y, input_line.c_str()+str_start);
355+
if (shelve_end != '\0') {
356+
input_line[str_end] = shelve_end; // rollback
357+
}
301358
}
302359
std::graphics::graphflush();
303360
}
@@ -311,7 +368,7 @@ class Interpreter {
311368
}
312369
void execute() {
313370
while(1) {
314-
console.update_log(display);
371+
console.update_status(display);
315372
display.draw();
316373
console.draw();
317374
std::string input = console.read();
@@ -331,7 +388,7 @@ void start_logo() {
331388

332389
void cleanup_graphics() {
333390
std::graphics::closegraph();
334-
std::cout << "graphics closed" << std::endl;
391+
std::cout << "logo graphics closed" << std::endl;
335392
}
336393

337394
int main(int argc,char *argv[]) {

0 commit comments

Comments
 (0)