/**
 * 发送控件该变大小消息
 *
 * @param msg 必须是鼠标松开消息
 *
 * @return 0
 **/
si_t handle_widget_resize(union message * msg)
{
	struct rectangle* work_area = &global_wm.active_win_info_ptr->work_area;
	struct rectangle* area = &global_wm.active_win_info_ptr->area;
	/**
	 * 必须有活动窗口
	 **/
	if(global_wm.active_app_info_ptr == NULL && global_wm.active_win_info_ptr == NULL)
	{
		return 0;
	}
	/* 只处理松开消息 */
	if(msg->mouse.code != INPUT_CODE_MOUSE_L_KEY)
	{
		return 0;
	}

	if(l_frame_press == 1)
	{
		send_widget_resize_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr,
			work_area->x + widget_resize_old_x_offset, work_area->y, work_area->width - widget_resize_old_x_offset, work_area->height);

		screen_flush(area->x + widget_resize_old_x_offset, area->y, area->width - widget_resize_old_x_offset, area->height);
	}
	else if(t_frame_press == 1)
	{
		send_widget_resize_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr,
			work_area->x, work_area->y + widget_resize_old_y_offset, work_area->width, work_area->height - widget_resize_old_y_offset);

		screen_flush(area->x, area->y + widget_resize_old_y_offset, area->width, area->height - widget_resize_old_y_offset);
	}
	else if(r_frame_press == 1)
	{
		send_widget_resize_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr,
			work_area->x, work_area->y, work_area->width + widget_resize_old_x_offset, work_area->height);

		screen_flush(area->x, area->y, area->width + widget_resize_old_x_offset, area->height);
	}
	else if(b_frame_press == 1)
	{
		send_widget_resize_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr,
			work_area->x, work_area->y, work_area->width, work_area->height + widget_resize_old_y_offset);

		screen_flush(area->x, area->y, area->width, area->height + widget_resize_old_y_offset);
	}

	cursor_paint();

	widget_resize_new_x_offset = 0;
	widget_resize_new_y_offset = 0;
	widget_resize_old_x_offset = 0;
	widget_resize_old_y_offset = 0;

	l_frame_press = 0;
	t_frame_press = 0;
	r_frame_press = 0;
	b_frame_press = 0;

	return 0;
}
Пример #2
0
int t_query(const char *uname)
{
	if (streq(currentuser.userid, "guest"))
		return DONOTHING;

	char userid[EXT_IDLEN + 1];
	if (uname) {
		if (*uname == '\0')
			return DONOTHING;
		strlcpy(userid, uname, sizeof(userid));
		strtok(userid, " ");
	} else {
		set_user_status(ST_QUERY);
		screen_flush();
		screen_move(2, 0);
		screen_clrtobot();
		screen_printf("<输入使用者代号, 按空白键可列出符合字串>");
		user_complete(1, "查询谁: ", userid, sizeof(userid));
		if (*userid == '\0')
			return FULLUPDATE;
	}

	if (tui_query_result(userid) != 0) {
		screen_move_clear(2);
		screen_printf("\033[1m不正确的使用者代号\033[m\n");
		pressanykey();
		return FULLUPDATE;
	}

	if (session_status() != ST_LUSERS && session_status() != ST_LAUSERS
			&& session_status() != ST_FRIEND && session_status() != ST_GMENU)
	pressanykey();
	return FULLUPDATE;
}
/**
 * 发送控件移动消息
 *
 * @param msg 必须是鼠标松开消息
 *
 * @return 0
 **/
static si_t handle_widget_move(union message * msg)
{
	/* 有包含窗口的用户应用程序 */
	if(global_wm.active_app_info_ptr != NULL && global_wm.active_win_info_ptr != NULL)
	{
		/* 松开消息 */
		if(msg->mouse.code == INPUT_CODE_MOUSE_L_KEY && title_bar_press == 1)
		{
			screen_flush
				(global_wm.active_win_info_ptr->area.x + widget_move_old_x_offset,
				 global_wm.active_win_info_ptr->area.y + widget_move_old_y_offset,
				 global_wm.active_win_info_ptr->area.width,
				 global_wm.active_win_info_ptr->area.height);

			cursor_paint();

			/* 发生了偏移 */
			if(widget_move_old_x_offset != 0 || widget_move_old_y_offset != 0)
			{
				send_widget_move_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr, 
					global_wm.active_win_info_ptr->work_area.x + widget_move_old_x_offset, 
					global_wm.active_win_info_ptr->work_area.y + widget_move_old_y_offset);
			}

			widget_move_old_x_offset = 0;
			widget_move_old_y_offset = 0;
			widget_move_new_x_offset = 0;
			widget_move_new_y_offset = 0;

			title_bar_press = 0;
		}
	}

	return 0;
}
Пример #4
0
/**
 * Get raw byte from stdin.
 * @return next byte from stdin
 */
static int get_raw_ch(void)
{
	if (input_buffer.cur >= input_buffer.size) {
		int fd = 0, ret;
		struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };

		while (1) {
			fd_set rset;
			FD_ZERO(&rset);
			FD_SET(STDIN_FILENO, &rset);

			int nfds = 1;
			if (fd > 0) {
				FD_SET(fd, &rset);
				nfds = fd + 1;
			}

			ret = select(nfds, &rset, NULL, NULL, &tv);

			if (FD_ISSET(STDIN_FILENO, &rset)) {
#ifdef ENABLE_SSH
				ret = channel_poll(ssh_chan, 0);
#endif
			}

			if (_schedule_exit || (ret < 0 && errno != EINTR))
				abort_bbs(0);

			if (ret <= 0) {
				screen_flush();
			} else {
				if (fd > 0 && FD_ISSET(fd, &rset)) {
					// TODO: handle notification
				}
				if (FD_ISSET(STDIN_FILENO, &rset)) {
					session_set_idle_cached();
					break;
				}
			}
			tv.tv_sec = IDLE_TIMEOUT;
			tv.tv_usec = 0;
		}

		while (1) {
			ret = terminal_read(input_buffer.ptr, sizeof(input_buffer.ptr));
			if (ret > 0)
				break;
			if (ret < 0 && (errno == EINTR))
				continue;
			abort_bbs(0);
		}
		input_buffer.cur = 0;
		input_buffer.size = ret;
	}
	return input_buffer.ptr[input_buffer.cur++];
}
Пример #5
0
int main(void) {
    buffer_t buf = buf_new(1);
    screen_t fake, real;

    int rows = 20, cols = 20;
    //read_dimensions(&rows, &cols);

    fake_screen_init(&fake, rows, cols);
    real_screen_init(&buf, &real, rows, cols);

    struct timespec req = {.tv_sec = 0, .tv_nsec = 100000000};
    struct timespec rem;

    int x, y;

    double cx = rows / 2.0,
           cy = cols / 2.0;

    double maxradius = sqrt(pow(cx, 2) + pow(cy, 2));

    int t = 0;
    while (t < 50) {
        for (x = 0; x < cols; x++) {
            for (y = 0; y < rows; y++) {
                int i = x + y*cols;
                int shade = 128 + 128*sin(t + sqrt(pow(x - cx, 2) + pow(y - cy, 2)));

                if (shade > 255) {
                    shade = 255;
                }

                fake.cells[i].style.back.r = shade;
                fake.cells[i].style.back.g = shade;
                fake.cells[i].style.back.b = shade;
            }
        }

        screen_flush(&buf, &fake, &real);
        write(STDOUT_FILENO, buf.data, buf.used);
        buf.used = 0;
        fake_screen_reset(&fake, rows, cols);
        
        t++;
        nanosleep(&req, &rem);
    }

    real_screen_cleanup(&buf, &real);
    write(STDOUT_FILENO, buf.data, buf.used);
    
    screen_free(&fake);
    screen_free(&real);
    buf_free(&buf);
}
Пример #6
0
static void system_abort(void)
{
	if (session_id()) {
		log_usies("ABORT", "", &currentuser);
		u_exit();
	}
	screen_clear();
	screen_flush();
	//% prints("谢谢光临, 记得常来喔 !\n");
	prints("\xd0\xbb\xd0\xbb\xb9\xe2\xc1\xd9, \xbc\xc7\xb5\xc3\xb3\xa3\xc0\xb4\xe0\xb8 !\n");
	exit(0);
}
Пример #7
0
Файл: friend.c Проект: fbbs/fbbs
static tui_list_query_t following_list_query(tui_list_t *p)
{
	p->in_query = true;
	if (t_query(following_list_get_name(p->data, p->cur)) == -1)
		return FULLUPDATE;
	screen_move_clear(-1);
	//% prints("\033[0;1;44;31m\033[33m 寄信 m │ 结束 Q,← │上一位 ↑│"
	prints("\033[0;1;44;31m\033[33m \xbc\xc4\xd0\xc5 m \xa9\xa6 \xbd\xe1\xca\xf8 Q,\xa1\xfb \xa9\xa6\xc9\xcf\xd2\xbb\xce\xbb \xa1\xfc\xa9\xa6"
			//% "下一位 <Space>,↓                            \033[m");
			"\xcf\xc2\xd2\xbb\xce\xbb <Space>,\xa1\xfd                            \033[m");
	screen_flush();
	return DONOTHING;
}
Пример #8
0
Файл: tui.c Проект: fbbs/fbbs
int pressreturn(void)
{
	extern int showansi;
	char buf[3];
	showansi = 1;
	screen_move_clear(-1);
	getdata(-1, 0,
			//% "                              请按 ◆Enter◆ 继续\033[m",
			"                              \xc7\xeb\xb0\xb4 \xa1\xf4Enter\xa1\xf4 \xbc\xcc\xd0\xf8\033[m",
			buf, 2, NOECHO, YEA);
	screen_move_clear(-1);
	screen_flush();
	return 0;
}
/**
 * 处理控件的移动
 *
 * 标记标题栏是否被按下
 *
 * @param msg 必须是鼠标移动消息
 *
 * @return 0
 **/
static si_t accumulate_widget_move(union message * msg)
{
	struct point p;

	/* 无包含窗口的用户应用程序 */
	if(global_wm.active_app_info_ptr == NULL && global_wm.active_win_info_ptr == NULL)
	{
		return 0;
	}
	if(title_bar_press != 1)
	{
		return 0;
	}

	screen_flush
		(global_wm.active_win_info_ptr->area.x + widget_move_old_x_offset,
		 global_wm.active_win_info_ptr->area.y + widget_move_old_y_offset,
		 global_wm.active_win_info_ptr->area.width,
		 global_wm.active_win_info_ptr->area.height);

	/* keep the cursor in desktop workarea */
	ensure_point_in_area(&global_wm.new_cursor, &global_wm.work_area);

	point_set(&p, 
		global_wm.active_win_info_ptr->area.x + widget_move_new_x_offset, global_wm.active_win_info_ptr->area.y + widget_move_new_y_offset);
	/* make sure window did not run away */
	ensure_point_in_area(&p, &global_wm.work_area);
	widget_move_old_x_offset = p.x - global_wm.active_win_info_ptr->area.x;
	widget_move_old_y_offset = p.y - global_wm.active_win_info_ptr->area.y;

	/* 绘制活动窗口的边框 */
	engine_draw_rectangle
		(global_wm.gd_handler,
		 global_wm.active_win_info_ptr->area.x + widget_move_old_x_offset,
		 global_wm.active_win_info_ptr->area.y + widget_move_old_y_offset,
		 global_wm.active_win_info_ptr->area.width,
		 global_wm.active_win_info_ptr->area.height);

	if(msg->mouse.code == INPUT_CODE_MOUSE_X_OFFSET)
	{
		widget_move_new_x_offset += global_wm.new_cursor.x - global_wm.old_cursor.x;
	}
	else if(msg->mouse.code == INPUT_CODE_MOUSE_Y_OFFSET)
	{
		widget_move_new_y_offset += global_wm.new_cursor.y - global_wm.old_cursor.y;
	}

	return 0;
}
Пример #10
0
void change_screen(uint8_t screen){
	if((console+screen)->type == SCREEN_UNUSED){
		return;
	}
	if(screen == current_screen){
		return;
	}
	if((console+screen)->type == SCREEN_CONSOLE){
		current_screen = screen;
		screen_flush();
	}else if((console+screen)->type == SCREEN_DESKTOP){
		current_screen = screen;
		desktop_screen_flush();
	}	
}
Пример #11
0
Файл: online.c Проект: fbbs/fbbs
static tui_list_query_t online_users_query(tui_list_t *p)
{
	online_users_t *up = p->data;
	online_user_info_t *ip = up->users + p->cur;
	p->in_query = true;

	t_query(ip->name);
	screen_move(-1, 0);
	//% prints("\033[0;1;37;44m聊天[\033[1;32mt\033[37m] 寄信[\033[1;32mm\033[37m] "
	prints("\033[0;1;37;44m\xc1\xc4\xcc\xec[\033[1;32mt\033[37m] \xbc\xc4\xd0\xc5[\033[1;32mm\033[37m] "
			//% "送讯息[\033[1;32ms\033[37m] 加,减朋友[\033[1;32mo\033[37m,\033[1;32md\033[37m] "
			"\xcb\xcd\xd1\xb6\xcf\xa2[\033[1;32ms\033[37m] \xbc\xd3,\xbc\xf5\xc5\xf3\xd3\xd1[\033[1;32mo\033[37m,\033[1;32md\033[37m] "
			//% "选择使用者[\033[1;32m↑\033[37m,\033[1;32m↓\033[37m] "
			"\xd1\xa1\xd4\xf1\xca\xb9\xd3\xc3\xd5\xdf[\033[1;32m\xa1\xfc\033[37m,\033[1;32m\xa1\xfd\033[37m] "
			//% "求救[\033[1;32mh\033[37m]");
			"\xc7\xf3\xbe\xc8[\033[1;32mh\033[37m]");
	screen_flush();
	return DONOTHING;
}
Пример #12
0
si_t debug_graph_lower()
{
    struct color c;
    struct screen s;
    struct rectangle a;

    /* 设置区域结构 */
    a.x = 0;
    a.y = 0;
    a.width = 101;
    a.height = 101;

    /* 获得屏幕资源 */
    memcpy(&s, &global_screen, sizeof(struct screen));

    /* 获得颜色资源 */
    screen_color_limit();

    printf("width      %ld\n", s.width);
    printf("height      %ld\n", s.height);
    printf("video_space %ld\n", s.size);
    printf("color_depth %ld\n", s.color_depth);

    printf("R 0 - %lX\n", global_color_limit.r_limit);
    printf("G 0 - %lX\n", global_color_limit.g_limit);
    printf("B 0 - %lX\n", global_color_limit.b_limit);
    printf("A 0 - %lX\n", global_color_limit.a_limit);

    c.r = global_color_limit.r_limit;
    c.g = 0;
    c.b = 0;

    /* 将屏幕清空成红色 */
    screen_clear(&s, &c);
    c.r = 127;
    c.g = 127;
    c.b = 127;

    screen_set_pixel(&s, &a, &c, -100, -100);
    screen_cpy_area
    (s.memory_addr,
     s.buffer_addr,
     0,
     0,
     0,
     0,
     s.width,
     s.height);
    sleep(1);

    screen_set_h_line(&s, &a, &c, -100, 50, 200, 50);
    screen_cpy_area
    (s.memory_addr,
     s.buffer_addr,
     0,
     0,
     0,
     0,
     s.width,
     s.height);
    sleep(1);

    screen_set_v_line(&s, &a, &c, 50, -100, 50, 200);
    screen_cpy_area
    (s.memory_addr,
     s.buffer_addr,
     0,
     0,
     0,
     0,
     s.width,
     s.height);
    sleep(1);

    screen_set_x_line(&s, &a, &c, -100, -100, 200, 200);
    screen_cpy_area
    (s.memory_addr,
     s.buffer_addr,
     0,
     0,
     0,
     0,
     s.width,
     s.height);
    sleep(1);

    screen_set_x_line(&s, &a, &c, -100, 200, 200, -100);
    screen_cpy_area
    (s.memory_addr,
     s.buffer_addr,
     0,
     0,
     0,
     0,
     s.width,
     s.height);
    sleep(1);

    screen_set_area(&s, &a, &c, -100, -100, 300, 300);
    screen_cpy_area
    (s.memory_addr,
     s.buffer_addr,
     0,
     0,
     0,
     0,
     s.width,
     s.height);
    sleep(1);

    /* 将屏幕清空成黑色 */
    screen_clear_black(&s);
    screen_cpy_area
    (s.memory_addr,
     s.buffer_addr,
     16,
     16,
     16,
     16,
     s.width - 16,
     s.height - 16);
    sleep(1);

    a.x = 0;
    a.y = 0;
    a.width = s.width;
    a.height = s.height;

    c.r = global_color_limit.r_limit;
    c.g = global_color_limit.g_limit;
    c.b = global_color_limit.b_limit;

    screen_set_area(&s, &a, &c, 100, 668, 200, 200);
    c.b = 0;
    screen_set_area(&s, &a, &c, -100, 200, 200, 200);
    screen_cpy_area
    (s.buffer_addr,
     s.buffer_addr,
     -100,
     200,
     100,
     668,
     200,
     200);
    screen_flush(0, 0, s.width, s.height);
    sleep(1);

    /* 复制有重叠的区域 */
    c.r = 0;
    c.g = global_color_limit.g_limit;
    c.b = 0;

    screen_set_area(&s, &a, &c, 0, 0, 300, 300);

    c.r = global_color_limit.r_limit;
    c.g = global_color_limit.g_limit;
    c.b = 0;

    screen_set_area(&s, &a, &c, 300, 0, 300, 300);
    screen_flush(0, 0, s.width, s.height);
    sleep(1);

    screen_cpy_area
    (s.memory_addr,
     s.memory_addr,
     300,
     100,
     200,
     0,
     200,
     200);

    sleep(1);

    printf("debuged graph_lower\n");

    return 0;
}
Пример #13
0
Файл: tui.c Проект: fbbs/fbbs
static int _tui_input(int line, int col, const char *prompt, char *buf,
		int len, int echo, int clear, bool utf8)
{
	extern int RMSG;
	extern int msg_num;

	if (clear)
		buf[0] = '\0';
	buf[len - 1] = '\0';

	int real_x = prompt ? screen_display_width(prompt, utf8) : 0;

	int cur, clen;
	cur = clen = strlen(buf);

	bool inited = screen_inited(), prompted = false;
	while (1) {
		if (inited || !prompted) {
			screen_move(line, col);
			clrtoeol();
			if (prompt) {
				if (utf8)
					screen_printf("%s", prompt);
				else
					prints("%s", prompt);
			}
			prompted = true;
		}
		if (inited) {
			if (echo)
				prints("%s", buf);
			else
				tui_repeat_char('*', clen);
			screen_move(line, real_x + cur);
		}

		if (RMSG)
			screen_flush();

		int ch = terminal_getchar();

		if (RMSG && msg_num == 0) {
			if (ch == Ctrl('Z') || ch == KEY_UP) {
				buf[0] = Ctrl('Z');
				clen = 1;
				break;
			}
			if (ch == Ctrl('A') || ch == KEY_DOWN) {
				buf[0] = Ctrl('A');
				clen = 1;
				break;
			}
		}

		if (ch == '\n' || ch == '\r')
			break;

		if (!inited) {
			if (ch == '\x7f' || ch == Ctrl('H')) {
				int dec = remove_character(buf, &cur, clen, true);
				if (dec) {
					clen -= dec;
					screen_puts("\x8 \x8", 3);
				}
			} else if (isprint2(ch) && clen < len - 1) {
				buf[cur] = ch;
				buf[++cur] = '\0';
				++clen;
				screen_putc(echo ? ch : '*');
			}
			continue;
		}

		if (ch == '\x7f' || ch == Ctrl('H')) {
			clen -= remove_character(buf, &cur, clen, true);
		} else if (ch == KEY_DEL) {
			clen -= remove_character(buf, &cur, clen, false);
		} else if (ch == KEY_LEFT) {
			if (cur > 0)
				--cur;
		} else if (ch == KEY_RIGHT) {
			if (cur < clen)
				++cur;
		} else if (ch == Ctrl('E') || ch == KEY_END) {
			cur = clen;
		} else if (ch == Ctrl('A') || ch == KEY_HOME) {
			cur = 0;
		} else if (isprint2(ch) && clen < len - 1) {
			if (buf[cur] != '\0')
				memmove(buf + cur + 1, buf + cur, clen - cur);
			buf[cur++] = ch;
			buf[++clen] = '\0';
		}
	}

	screen_putc('\n');
	screen_flush();
	return clen;
}
Пример #14
0
/**
 * Telnet register interface.
 */
void new_register(void)
{
	char userid[IDLEN + 1], passwd[PASSLEN], passbuf[PASSLEN], log[STRLEN];
	const char *errmsg;

	if (register_closed()) {
		ansimore("NOREGISTER", NA);
		pressreturn();
		return;
	}

	ansimore("etc/register", NA);
#ifndef FDQUAN
	//% if (!askyn("您是否同意本站Announce版精华区x-3目录所列站规?", false, false))
	if (!askyn("\xc4\xfa\xca\xc7\xb7\xf1\xcd\xac\xd2\xe2\xb1\xbe\xd5\xbe""Announce\xb0\xe6\xbe\xab\xbb\xaa\xc7\xf8x-3\xc4\xbf\xc2\xbc\xcb\xf9\xc1\xd0\xd5\xbe\xb9\xe6?", false, false))
		return;
#endif

	int tried = 0;
	prints("\n");
	while (1) {
		if (++tried >= MAX_NEW_TRIES) {
			//% outs("\n拜拜,按太多下  <Enter> 了...\n");
			outs("\n\xb0\xdd\xb0\xdd\xa3\xac\xb0\xb4\xcc\xab\xb6\xe0\xcf\xc2  <Enter> \xc1\xcb...\n");
			screen_flush();
			return;
		}

		//% getdata(0, 0, "请输入帐号名称 (Enter User ID, \"0\" to abort): ",
		getdata(0, 0, "\xc7\xeb\xca\xe4\xc8\xeb\xd5\xca\xba\xc5\xc3\xfb\xb3\xc6 (Enter User ID, \"0\" to abort): ",
				userid, sizeof(userid), DOECHO, YEA);
		if (userid[0] == '0')
			return;
		errmsg = register_invalid_user_name(userid);
		if (errmsg != NULL) {
			outs(errmsg);
			continue;
		}

		char path[HOMELEN];
		sethomepath(path, userid);
		if (dosearchuser(userid, &currentuser, &usernum) || dashd(path)) {
			//% outs("此帐号已经有人使用\n");
			outs("\xb4\xcb\xd5\xca\xba\xc5\xd2\xd1\xbe\xad\xd3\xd0\xc8\xcb\xca\xb9\xd3\xc3\n");
			continue;
		}
#ifndef REG_CAPTCHA
		break;
#else
		char link[STRLEN], attempt[CAPTCHA_LEN + 1], answer[CAPTCHA_LEN + 1];
		int lnum;
		int pos = gen_captcha_link(link, sizeof(link), &lnum);
		if (pos < 0)
			return;

		prints("http://"BBSHOST"/captcha/%d.gif\n", lnum);
		//% getdata(0, 0, "请输入上图所包含的英文字母: ", attempt, sizeof(attempt),
		getdata(0, 0, "\xc7\xeb\xca\xe4\xc8\xeb\xc9\xcf\xcd\xbc\xcb\xf9\xb0\xfc\xba\xac\xb5\xc4\xd3\xa2\xce\xc4\xd7\xd6\xc4\xb8: ", attempt, sizeof(attempt),
				DOECHO, YEA);
		unlink(link);

		get_captcha_answer(pos, answer, sizeof(answer));
		if (strcasecmp(answer, attempt) != 0) {
			//% outs("验证码输入错误...\n");
			outs("\xd1\xe9\xd6\xa4\xc2\xeb\xca\xe4\xc8\xeb\xb4\xed\xce\xf3...\n");
			continue;
		} else {
			break;
		}
#endif // REG_CAPTCHA
	}

	for (tried = 0; tried <= MAX_SET_PASSWD_TRIES; ++tried) {
		passbuf[0] = '\0';
		//% getdata(0, 0, "请设定您的密码 (Setup Password): ", passbuf,
		getdata(0, 0, "\xc7\xeb\xc9\xe8\xb6\xa8\xc4\xfa\xb5\xc4\xc3\xdc\xc2\xeb (Setup Password): ", passbuf,
				sizeof(passbuf), NOECHO, YEA);
		errmsg = register_invalid_password(passbuf, userid);
		if (errmsg) {
			outs(errmsg);
			continue;
		}
		strlcpy(passwd, passbuf, PASSLEN);
		//% getdata(0, 0, "请再输入一次您的密码 (Confirm Password): ", passbuf,
		getdata(0, 0, "\xc7\xeb\xd4\xd9\xca\xe4\xc8\xeb\xd2\xbb\xb4\xce\xc4\xfa\xb5\xc4\xc3\xdc\xc2\xeb (Confirm Password): ", passbuf,
				PASSLEN, NOECHO, YEA);
		if (strncmp(passbuf, passwd, PASSLEN) != 0) {
			//% prints("密码输入错误, 请重新输入密码\n");
			prints("\xc3\xdc\xc2\xeb\xca\xe4\xc8\xeb\xb4\xed\xce\xf3, \xc7\xeb\xd6\xd8\xd0\xc2\xca\xe4\xc8\xeb\xc3\xdc\xc2\xeb\n");
			continue;
		}
		passwd[8] = '\0';
		break;
	}
	if (tried > MAX_SET_PASSWD_TRIES)
		return;

	struct userec user;
	init_userec(&user, userid, passwd, true);
	strlcpy(user.lasthost, fromhost, sizeof(user.lasthost));

	if (create_user(&user) < 0) {
		outs("Failed to create user.\n");
		return;
	}

	snprintf(log, sizeof(log), "new account from %s", fromhost);
	report(log, currentuser.userid);

	//% prints("请重新登录 %s 并填写注册信息\n", user.userid);
	prints("\xc7\xeb\xd6\xd8\xd0\xc2\xb5\xc7\xc2\xbc %s \xb2\xa2\xcc\xee\xd0\xb4\xd7\xa2\xb2\xe1\xd0\xc5\xcf\xa2\n", user.userid);
	pressanykey();
	return;
}
Пример #15
0
// Do autoposting according to "etc/autopost",
// if no such action has been taken since last 00:00 UTC.
static void notepad_init(void)
{
	FILE *check;
	char notetitle[STRLEN];
	char tmp[STRLEN * 2];
	char *fname, *bname, *ntitle;
	long int maxsec;

	maxsec = 86400;
	lastnote = 0;
	if ((check = fopen("etc/checknotepad", "r")) != NULL) {
		fgets(tmp, sizeof(tmp), check);
		lastnote = atol(tmp);
		fclose(check);
	}
	fb_time_t now = fb_time();
	if ((now - lastnote) >= maxsec) {
		screen_move(-1, 0);
		//% prints("对不起,系统自动发信,请稍候.....");
		prints("\xb6\xd4\xb2\xbb\xc6\xf0\xa3\xac\xcf\xb5\xcd\xb3\xd7\xd4\xb6\xaf\xb7\xa2\xd0\xc5\xa3\xac\xc7\xeb\xc9\xd4\xba\xf2.....");
		screen_flush();
		check = fopen("etc/checknotepad", "w");
		lastnote = now - (now % maxsec);
		if (check) {
			fprintf(check, "%ld", lastnote);
			fclose(check);
		}
		if ((check = fopen("etc/autopost", "r")) != NULL) {
			while (fgets(tmp, STRLEN, check) != NULL) {
				fname = strtok(tmp, " \n\t:@");
				bname = strtok(NULL, " \n\t:@");
				ntitle = strtok(NULL, " \n\t:@");
				if (fname == NULL || bname == NULL || ntitle == NULL)
					continue;
				else {
					char *str = format_time(now, TIME_FORMAT_ZH);
					snprintf(notetitle, sizeof(notetitle), "[%14.14s %6.6s] %s",
							str, str + 23, ntitle);
					if (dashf(fname)) {
						Postfile(fname, bname, notetitle, 1);
						//% sprintf(tmp, "%s 自动张贴", ntitle);
						sprintf(tmp, "%s \xd7\xd4\xb6\xaf\xd5\xc5\xcc\xf9", ntitle);
						report(tmp, currentuser.userid);
					}
				}
			}
			fclose(check);
		}
		char *str = format_time(now, TIME_FORMAT_ZH);
		//% snprintf(notetitle, sizeof(notetitle), "[%14.14s %6.6s] 留言板记录",
		snprintf(notetitle, sizeof(notetitle), "[%14.14s %6.6s] \xc1\xf4\xd1\xd4\xb0\xe5\xbc\xc7\xc2\xbc",
				str, str + 23);
		if (dashf("etc/notepad")) {
			Postfile("etc/notepad", "Notepad", notetitle, 1);
			unlink("etc/notepad");
		}
		//% report("自动发信时间更改", currentuser.userid);
		report("\xd7\xd4\xb6\xaf\xb7\xa2\xd0\xc5\xca\xb1\xbc\xe4\xb8\xfc\xb8\xc4", currentuser.userid);
	}
	return;
}
/**
 * 处理控件的移动
 *
 * 标记标题栏是否被按下
 *
 * @param msg 必须是鼠标移动消息
 *
 * @return 0
 **/
static si_t accumulate_widget_resize(union message * msg)
{
	struct rectangle* win_work_area = &global_wm.active_win_info_ptr->work_area;
	struct rectangle* win_area = &global_wm.active_win_info_ptr->area;
	NOT_USED(msg);

	if(global_wm.active_app_info_ptr == NULL && global_wm.active_win_info_ptr == NULL)
	{
		return 0;
	}
	/* 左边框 */
	if(l_frame_press == 1)
	{
		screen_flush(win_area->x + widget_resize_old_x_offset, win_area->y, win_area->width - widget_resize_old_x_offset, win_area->height);

		widget_resize_new_x_offset += global_wm.new_cursor.x - global_wm.old_cursor.x;

		/* 向右拉左边框:检查窗口宽是否超出最小宽度 */
		if(widget_resize_new_x_offset > 0 && win_work_area->width - widget_resize_new_x_offset < window_info_least_width(global_wm.active_win_info_ptr))
		{
			widget_resize_old_x_offset = win_work_area->width - window_info_least_width(global_wm.active_win_info_ptr);
		}
		else
		{
			widget_resize_old_x_offset = widget_resize_new_x_offset;
		}

		/* 绘制活动窗口的边框 */
		engine_draw_rectangle(global_wm.gd_handler,
			win_area->x + widget_resize_old_x_offset, win_area->y, win_area->width - widget_resize_old_x_offset, win_area->height);
	}
	/* 上边框 */
	else if(t_frame_press == 1)
	{
		screen_flush(win_area->x, win_area->y + widget_resize_old_y_offset, win_area->width, win_area->height - widget_resize_old_y_offset);

		widget_resize_new_y_offset += global_wm.new_cursor.y - global_wm.old_cursor.y;

		/* 向下拉上边框:检查窗口高度是否超出最小高度 */
		if(widget_resize_new_y_offset > 0 && win_work_area->height - widget_resize_new_y_offset < 0)
		{
			widget_resize_old_y_offset = win_work_area->height;
		}
		else
		{
			widget_resize_old_y_offset = widget_resize_new_y_offset;
		}

		/* 绘制活动窗口的边框 */
		engine_draw_rectangle(global_wm.gd_handler,
			win_area->x, win_area->y + widget_resize_old_y_offset, win_area->width, win_area->height - widget_resize_old_y_offset);
	}
	/* 右边框 */
	else if(r_frame_press == 1)
	{
		screen_flush(win_area->x, win_area->y, win_area->width + widget_resize_old_x_offset, win_area->height);

		widget_resize_new_x_offset += global_wm.new_cursor.x - global_wm.old_cursor.x;

		/* 向左拉右边框:检查窗口宽是否超出最小宽度 */
		if(widget_resize_new_x_offset < 0 && win_work_area->width + widget_resize_new_x_offset < window_info_least_width(global_wm.active_win_info_ptr))
		{
			widget_resize_new_x_offset = window_info_least_width(global_wm.active_win_info_ptr) - win_work_area->width;
		}
		else
		{
			widget_resize_old_x_offset = widget_resize_new_x_offset;
		}

		/* 绘制活动窗口的边框 */
		engine_draw_rectangle(global_wm.gd_handler,
			win_area->x, win_area->y, win_area->width + widget_resize_old_x_offset, win_area->height);
	}
	/* 下边框 */
	else if(b_frame_press == 1)
	{
		screen_flush(win_area->x, win_area->y, win_area->width, win_area->height + widget_resize_old_y_offset);

		widget_resize_new_y_offset += global_wm.new_cursor.y - global_wm.old_cursor.y;

		/* 向上拉下边框:检查窗口高度是否超出最小高度 */
		if(widget_resize_new_y_offset < 0 && win_work_area->height + widget_resize_new_y_offset < 0)
		{
			widget_resize_old_y_offset = 0 - win_work_area->height;
		}
		else
		{
			widget_resize_old_y_offset = widget_resize_new_y_offset;
		}

		/* 绘制活动窗口的边框 */
		engine_draw_rectangle(global_wm.gd_handler,
			win_area->x, win_area->y, win_area->width, win_area->height + widget_resize_old_y_offset);
	}

	return 0;
}
Пример #17
0
int namecomplete(char *prompt, char *data) {
	char *temp;
	int ch;
	int count = 0;
	int clearbot = NA;
	struct word *cwlist, *morelist;
	int x, y;
	int origx, origy;

	if (prompt != NULL) {
		prints("%s", prompt);
		clrtoeol();
	}
	temp = data;

	if (toplev == NULL)
		AddNameList("");
	cwlist = GetSubList("", toplev);
	morelist = NULL;
	screen_coordinates(&y, &x);
	screen_coordinates(&origy, &origx);
	while ((ch = terminal_getchar()) != EOF) {
		if (ch == '\n' || ch == '\r') {
			*temp = '\0';
			prints("\n");
			if (NumInList(cwlist) == 1)
				strcpy(data, cwlist->name);
			else { /*  版面 ID 选择的一个精确匹配问题  period */
				struct word *list;
				for (list = cwlist; list != NULL; list = list->next) {
					if (!strcasecmp(data, list->name)) {
						strcpy(data, list->name);
						break;
					} //if
				} //for
			} //else
			ClearSubList(cwlist);
			break;
		}
		if (ch == ' ' || ch == KEY_TAB) {
			int col, len, i;
			if (NumInList(cwlist) == 1) {
				strcpy(data, cwlist->name);
				screen_move(y, x);
				prints("%s", data + count);
				count = strlen(data);
				temp = data + count;
				screen_coordinates(&y, &x);
				continue;
			}
			for (i = strlen(data); i && i < STRLEN; i++) {
				struct word *node;

				ch = cwlist->name[i];
				if (ch == '\0')
					break;
				for (node = cwlist; node; node = node->next) {
					if (toupper(ch) != toupper(node->name[i]))
						break;
				}
				if (node != NULL)
					break;
				*temp++ = ch;
				count++;
				*temp = '\0';
				node = GetSubList(data, cwlist);
				if (node == NULL) {
					temp--;
					*temp = '\0';
					count--;
					break;
				}
				ClearSubList(cwlist);
				cwlist = node;
				morelist = NULL;
				screen_move(y, x);
				outc(ch);
				x++;
			} //for
			clearbot = YEA;
			col = 0;
			if (!morelist)
				morelist = cwlist;
			len = MaxLen(morelist, NUMLINES);
			screen_move(origy + 1, 0);
			screen_clrtobot();
			prints(ANSI_CMD_SO);
			//% printdash(" 列表 ");
			printdash(" \xc1\xd0\xb1\xed ");
			prints(ANSI_CMD_SE);
			while (len + col < 80) {
				int i;
				for (i = NUMLINES; (morelist) && (i > origy - 1); i--) {
					if (morelist->name[0] != '\0') {
						screen_move(origy + 2 + (NUMLINES - i), col);
						prints("%s", morelist->name);
					} else {
						i++;
					}
					morelist = morelist->next;
				}
				col += len + 2;
				if (!morelist)
					break;
				len = MaxLen(morelist, NUMLINES);
			} //while
			if (morelist) {
				screen_move(-1, 0);
				//% prints("-- 还有 --                                                                     ");
				prints("-- \xbb\xb9\xd3\xd0 --                                                                     ");
			}
			screen_move(y, x);
			continue;
		}
		if (ch == '\177' || ch == '\010') {
			if (temp == data)
				continue;
			temp--;
			count--;
			*temp = '\0';
			ClearSubList(cwlist);
			cwlist = GetSubList(data, toplev);
			morelist = NULL;
			x--;
			screen_move(y, x);
			outc(' ');
			screen_move(y, x);
			continue;
		} //if
		if (count < STRLEN) {
			struct word *node;
			*temp++ = ch;
			count++;
			*temp = '\0';
			node = GetSubList(data, cwlist);
			if (node == NULL) {
				temp--;
				*temp = '\0';
				count--;
				continue;
			}
			ClearSubList(cwlist);
			cwlist = node;
			morelist = NULL;
			screen_move(y, x);
			outc(ch);
			x++;
		}
	} // while
	if (ch == EOF)
		longjmp(byebye, -1);
	prints("\n");
	screen_flush();
	if (clearbot) {
		screen_move(origy, 0);
		screen_clrtobot();
	}
	if (*data) {
		screen_move(origy, origx);
		prints("%s\n", data);
		/* for (x=1; x<500; x++);  delay */
	}
	return 0;
}
Пример #18
0
int usercomplete(char *prompt, char *data) {
	char *cwbuf, *cwlist, *temp;
	int cwnum, x, y, origx, origy;
	int clearbot = NA, count = 0, morenum = 0;
	char ch;

	cwbuf = malloc(MAXUSERS * (IDLEN + 1));
	if (prompt != NULL) {
		prints("%s", prompt);
		clrtoeol();
	}
	temp = data;
	cwlist = u_namearray((void *)cwbuf, &cwnum, "");
	screen_coordinates(&y, &x);
	screen_coordinates(&origy, &origx);
	while ((ch = terminal_getchar()) != EOF) {
		if (ch == '\n' || ch == '\r') {
			int i;
			char *ptr;

			*temp = '\0';
			prints("\n");
			ptr = cwlist;
			for (i = 0; i < cwnum; i++) {
				if (strncasecmp(data, ptr, IDLEN + 1) == 0)
					strcpy(data, ptr);
				ptr += IDLEN + 1;
			}
			/* if( cwnum == 1 ) strcpy( data, cwlist ); */
			break;
		} // if
		if (ch == ' ' || ch == KEY_TAB) {
			int col, len, i, j;
			int n;

			if (cwnum == 1) {
				strcpy(data, cwlist);
				screen_move(y, x);
				prints("%s", data + count);
				count = strlen(data);
				temp = data + count;
				screen_coordinates(&y, &x);
				continue;
			}
			for (i = strlen(data); i && i < IDLEN; i++) {
				ch = cwlist[i];
				if (ch == '\0')
					break;
				for (j = 0; j < cwnum; j++) {
					if (toupper((cwlist + (IDLEN + 1) * j)[i]) != toupper(ch))
						break;
				}
				if (j != cwnum)
					break;
				*temp++ = ch;
				*temp = '\0';
				n = UserSubArray((void *)cwbuf, (void *)cwlist, cwnum, ch,
						count);
				if (n == 0) {
					temp--;
					*temp = '\0';
					break;
				}
				cwlist = cwbuf;
				count++;
				cwnum = n;
				morenum = 0;
				screen_move(y, x);
				outc(ch);
				x++;
			}
			clearbot = YEA;
			col = 0;
			len = UserMaxLen((void *)cwlist, cwnum, morenum, NUMLINES);
			screen_move(origy + 1, 0);
			screen_clrtobot();
			//% printdash(" 所有使用者列表 ");
			printdash(" \xcb\xf9\xd3\xd0\xca\xb9\xd3\xc3\xd5\xdf\xc1\xd0\xb1\xed ");
			while (len + col < 79) {
				int i;
				for (i = 0; morenum < cwnum && i < NUMLINES - origy + 1; i++) {
					char *tmpptr = cwlist + (IDLEN + 1) * morenum++;
					if (*tmpptr != '\0') { //by Eric
						screen_move(origy + 2 + i, col);
						prints("%s ", tmpptr);
					} else
						i--;
				}
				col += len + 2;
				if (morenum >= cwnum)
					break;
				len = UserMaxLen((void *)cwlist, cwnum, morenum, NUMLINES);
			}
			if (morenum < cwnum) {
				screen_move(-1, 0);
				//% prints("-- 还有使用者 --                                                               ");
				prints("-- \xbb\xb9\xd3\xd0\xca\xb9\xd3\xc3\xd5\xdf --                                                               ");
			} else {
				morenum = 0;
			}
			screen_move(y, x);
			continue;
		}
		if (ch == '\177' || ch == '\010') {
			if (temp == data)
				continue;
			temp--;
			count--;
			*temp = '\0';
			cwlist = u_namearray((void *)cwbuf, &cwnum, data);
			morenum = 0;
			x--;
			screen_move(y, x);
			outc(' ');
			screen_move(y, x);
			continue;
		}
		if (count < STRLEN) {
			int n;
			*temp++ = ch;
			*temp = '\0';
			n = UserSubArray((void *)cwbuf, (void *)cwlist, cwnum, ch,
					count);
			if (n == 0) {
				temp--;
				*temp = '\0';
				continue;
			}
			cwlist = cwbuf;
			count++;
			cwnum = n;
			morenum = 0;
			screen_move(y, x);
			outc(ch);
			x++;
		}
	}
	free(cwbuf);
	if (ch == EOF)
		longjmp(byebye, -1);
	prints("\n");
	screen_flush();
	if (clearbot) {
		screen_move(origy, 0);
		screen_clrtobot();
	}
	if (*data) {
		screen_move(origy, origx);
		prints("%s\n", data);
	}
	return 0;
}
Пример #19
0
static void user_login(void)
{
	char fname[STRLEN];

	// SYSOP gets all permission bits when login.
	if (strcmp(currentuser.userid, "SYSOP") == 0) {
		currentuser.userlevel = ~0;
		substitut_record(PASSFILE, &currentuser, sizeof(currentuser),
				usernum);
	}
	fromhost[sizeof(fromhost) - 1] = 0; //added by iamfat 2004.01.05 to avoid overflow
	log_usies("ENTER", fromhost, &currentuser);

	SpecialID(currentuser.userid, fromhost, sizeof(fromhost));

	u_enter();
	report("Enter", currentuser.userid);

#ifdef USE_NOTEPAD
	notepad_init();
	if (strcmp(currentuser.userid, "guest") != 0) {
		if (DEFINE(DEF_NOTEPAD)) {
			int noteln;

			if (lastnote> currentuser.notedate)
			currentuser.noteline = 0;
			noteln = countln("etc/notepad");
			if (currentuser.noteline == 0) {
				shownotepad();
			} else if ((noteln - currentuser.noteline)> 0) {
				screen_move(0, 0);
				ansimore2("etc/notepad", NA, 0, noteln - currentuser.noteline + 1);
				terminal_getchar();
				screen_clear();
			}
			currentuser.noteline = noteln;
			write_defnotepad();
		}
	}
#endif

	if (show_statshm("etc/hotspot", 0)) {
		screen_flush();
		pressanykey();
	}

	if ((vote_flag(NULL, '\0', 2 /* 检查读过新的Welcome 没 */) == 0)) {
		if (dashf("Welcome")) {
			ansimore("Welcome", YEA);
			vote_flag(NULL, 'R', 2 /* 写入读过新的Welcome */);
		}
	} else {
		ansimore("Welcome2", YEA);
	}
	show_statshm("0Announce/bbslist/day", 1);
	screen_flush();
	screen_move_clear(-2);
	if (currentuser.numlogins < 1) {
		currentuser.numlogins = 0;
		//% prints("\033[1;36m☆ 这是您第 \033[33m1\033[36m 次拜访本站,请记住今天吧。\n");
		prints("\033[1;36m\xa1\xee \xd5\xe2\xca\xc7\xc4\xfa\xb5\xda \033[33m1\033[36m \xb4\xce\xb0\xdd\xb7\xc3\xb1\xbe\xd5\xbe\xa3\xac\xc7\xeb\xbc\xc7\xd7\xa1\xbd\xf1\xcc\xec\xb0\xc9\xa1\xa3\n");
		//% prints("☆ 您第一次连入本站的时间为 \033[33m%s\033[m ", format_time(time(NULL), TIME_FORMAT_ZH));
		prints("\xa1\xee \xc4\xfa\xb5\xda\xd2\xbb\xb4\xce\xc1\xac\xc8\xeb\xb1\xbe\xd5\xbe\xb5\xc4\xca\xb1\xbc\xe4\xce\xaa \033[33m%s\033[m ", format_time(fb_time(), TIME_FORMAT_ZH));
	} else {
		prints(
				//% "\033[1;36m☆ 这是您第 \033[33m%d\033[36m 次拜访本站,上次您是从 \033[33m%s\033[36m 连往本站。\n",
				"\033[1;36m\xa1\xee \xd5\xe2\xca\xc7\xc4\xfa\xb5\xda \033[33m%d\033[36m \xb4\xce\xb0\xdd\xb7\xc3\xb1\xbe\xd5\xbe\xa3\xac\xc9\xcf\xb4\xce\xc4\xfa\xca\xc7\xb4\xd3 \033[33m%s\033[36m \xc1\xac\xcd\xf9\xb1\xbe\xd5\xbe\xa1\xa3\n",
				currentuser.numlogins + 1, currentuser.lasthost);
		//% prints("☆ 上次连线时间为 \033[33m%s\033[m ", format_time(currentuser.lastlogin, TIME_FORMAT_ZH));
		prints("\xa1\xee \xc9\xcf\xb4\xce\xc1\xac\xcf\xdf\xca\xb1\xbc\xe4\xce\xaa \033[33m%s\033[m ", format_time(currentuser.lastlogin, TIME_FORMAT_ZH));
	}
	terminal_getchar();
	setuserfile(fname, BADLOGINFILE);
	if (ansimore(fname, NA) != -1) {
		//% if (askyn("您要删除以上密码输入错误的记录吗", NA, NA) == YEA)
		if (askyn("\xc4\xfa\xd2\xaa\xc9\xbe\xb3\xfd\xd2\xd4\xc9\xcf\xc3\xdc\xc2\xeb\xca\xe4\xc8\xeb\xb4\xed\xce\xf3\xb5\xc4\xbc\xc7\xc2\xbc\xc2\xf0", NA, NA) == YEA)
			unlink(fname);
	}

	set_safe_record();
	tui_check_uinfo(&currentuser);
	strlcpy(currentuser.lasthost, fromhost, sizeof(currentuser.lasthost));
	if (login_start_time - currentuser.lastlogin >= 20 * 60
			|| !strcmp(currentuser.userid, "guest")
			|| currentuser.numlogins < 100) {
		currentuser.numlogins++;
	}

	session_basic_info_t *res = get_my_sessions();
	update_user_stay(&currentuser, true, session_basic_info_count(res) > 1);
	session_basic_info_clear(res);

#ifdef ALLOWGAME
	if (currentuser.money> 1000000) {
		currentuser.nummedals += currentuser.money / 10000;
		currentuser.money %= 1000000;
	}
	if ((signed int) (currentuser.money - currentuser.bet) < -4990
			&& currentuser.numlogins < 10 && currentuser.numposts < 10
			&& currentuser.nummedals == 0)
	currentuser.money += 1000;
#endif
	if (currentuser.firstlogin == 0) {
		currentuser.firstlogin = time(NULL) - 7 * 86400;
	}
	substitut_record(PASSFILE, &currentuser, sizeof(currentuser), usernum);
	extern char currmaildir[];
	setmdir(currmaildir, currentuser.userid);
	check_register_info();
}
Пример #20
0
int main(void) {
    buffer_t buf = buf_new(1);
    screen_t fake, real;

    int rows, cols;
    read_dimensions(&rows, &cols);

    fake_screen_init(&fake, rows, cols);
    real_screen_init(&buf, &real, rows, cols);
    prepare_events();

    int x = 0,
        y = 0;
    char text[cols*rows];
    bool marks[cols*rows];

    memset(text, ' ', sizeof text);
    memset(marks, 0, sizeof marks);

await: {
    event_t e = await_event();

    switch (e.type) {
    case E_SIG:
        goto quit;
    break;
    case E_KEY:
        switch (e.key) {
        case '\b':
            if (x > 0) x -= 1;
        break;
        case '\n': x  = 0; y += 1; break;
        case '~':
            marks[x + y*cols] = !marks[x + y*cols];
            x++;
        break;
        default:
            text[x + y*cols] = e.key;
            x++;
        break;
        }
    break;
    case E_UP: y -= 1; break;
    case E_DOWN: y += 1; break;
    case E_LEFT: x -= 1; break;
    case E_RIGHT: x += 1; break;
    default:
    break;
    }

    int cx, cy;
    for (cx = 0; cx < cols; cx++) {
        for (cy = 0; cy < rows; cy++) {
            fake.cells[cx + cy*cols].codes[0] = text[cx + cy*cols];
        }
    }

    int j;
    for (j = 0; j < cols*rows; j++) {
        if (marks[j]) {
            fake.cells[j].style.back.rgb = 0xff0000;
        }
    }

    fake.cursor.x = x;
    fake.cursor.y = y;
    fake.cursor.visible = true;

    screen_flush(&buf, &fake, &real);
    write(STDOUT_FILENO, buf.data, buf.used);
    buf.used = 0;
    fake_screen_reset(&fake, 25, 80);

    goto await;
}

quit:
    cleanup_events();
    real_screen_cleanup(&buf, &real);
    write(STDOUT_FILENO, buf.data, buf.used);
    
    screen_free(&fake);
    screen_free(&real);
    buf_free(&buf);

    return 0;
}