/* 屏幕向上滚动 函数不检查状态变化的合法性,是否处于可滚动状态由调用者判断 因此,此函数不要直接调用 */ static void erase_upward_console_screen(unsigned int new_line_idx/*, bool rolling_one_line*/) { unsigned int new_line = new_line_idx; unsigned int erased_line = dsp_ctx.window.topline; unsigned int erased_pos_x = 0; unsigned int erased_pos_y = 0; unsigned int new_pos_x = 0; unsigned int new_pos_y = 0; unsigned int count, erased_count; int i; reset_up_idx(); dsp_ctx.window.topline = new_line; while(1) { dsp_ctx.color = BLACK_PIX; erased_count = draw_a_line(&erased_pos_x, &erased_pos_y, erased_line, dsp_ctx.buffer.lastchar); /* 向屏幕打印替代的行 */ if (new_line != dsp_ctx.buffer.lastchar) { dsp_ctx.color = WHITE_PIX; count = draw_a_line(&new_pos_x, &new_pos_y, new_line, dsp_ctx.buffer.lastchar); dsp_ctx.window.lastchar = get_buf_idx(new_line + count); new_line = get_buf_idx(new_line + count); if ( new_line == dsp_ctx.buffer.lastchar) { dsp_ctx.window.downward = 0; } else { modify_up_idx(new_pos_x, new_pos_y); } } /* 屏幕刷新完毕 */ if (erased_pos_y >= dsp_ctx.max_y - 20) break; erased_line = get_buf_idx(erased_line + erased_count); } /* 维护相关数据 */ dsp_ctx.window.pos_x = new_pos_x; dsp_ctx.window.pos_y = new_pos_y; dsp_ctx.color = WHITE_PIX; return; }
/* draw the background of the playing board */ static void draw_background(GooCanvasItem *rootItem) { int x,y,x1,y1; int wall; /*draw the lines*/ for (x1=0; x1< breedte; x1++) { for (y1=0; y1 < hoogte; y1++) { wall=Maze[x1][y1];; y=cellsize*(y1)+board_border_y; x=cellsize*(x1)+board_border_x; if (x1==0) draw_a_line(rootItem, x, y, x, y+cellsize, WALL_COLOR); if (y1==0) draw_a_line(rootItem, x, y, x+cellsize, y, WALL_COLOR); if (wall&EAST) draw_a_line(rootItem, x+cellsize, y, x+cellsize, y+cellsize, WALL_COLOR); if (wall&SOUTH) draw_a_line(rootItem,x, y+cellsize, x+cellsize, y+cellsize, WALL_COLOR); } } }
/** @brief 接口,分辨率变更处理函数, 环境不足,因此目前未测试 @width[in] @height[in] @return void */ void modify_screen_resolution(unsigned long width, unsigned long height) { int count = 0; /* 重绘屏幕 且屏幕首行保持不变 */ dsp_ctx.max_x = width; dsp_ctx.max_y = height; dsp_ctx.window.pos_x = 0; dsp_ctx.window.pos_y = 0; reset_up_idx(); dsp_ctx.window.lastchar = get_buf_idx(dsp_ctx.window.topline); while (1) { /* 屏幕满,向上滚动 */ if (dsp_ctx.window.pos_y >= dsp_ctx.max_y - 20) { break; } if (dsp_ctx.window.lastchar == dsp_ctx.buffer.lastchar) { dsp_ctx.window.downward = 0; break; } else { /*打印一行(指屏幕)数据,或者不足一行时打印到缓存最后一个字符 count为本次处理的字节数 */ count = draw_a_line(&dsp_ctx.window.pos_x, &dsp_ctx.window.pos_y, dsp_ctx.window.lastchar, dsp_ctx.buffer.lastchar); /* 更新窗口的状态 */ dsp_ctx.window.lastchar = get_buf_idx(dsp_ctx.window.lastchar + count); modify_up_idx(dsp_ctx.window.pos_x, dsp_ctx.window.pos_y); } } return; }
/* 入口函数 */ static int write_string(char *buffer, int size) { unsigned count = 0; unsigned int pos = 0; unsigned long flags; /* 数据长度超过缓存,直接舍弃 */ if (strlen(buffer) + 2 * sizeof(unsigned int) >= CONSOLE_BUFFER_SIZE) { goto ret; } /* 涉及两个全局资源,无法实现并发 只能加全局大锁 */ spin_lock_irqsave(&dsp_ctx.lock, flags); /* 第一步,将数据复制到缓存中,更新缓存的状态 */ /* 如果空间已经用完,则从头部循环使用 循环保证有足够的空间 */ while(1) { while (strlen(buffer) + get_buf_length(dsp_ctx.buffer.topline, dsp_ctx.buffer.lastchar) + (2 * sizeof(unsigned int)) >= CONSOLE_BUFFER_SIZE) { /* 刷掉缓存中的第一行数据(以输入的\n界定,不是以显示换行界定) */ dsp_ctx.buffer.topline = next_line_in_buffer(dsp_ctx.buffer.topline); /* 如果清空的数据正好处于当前显示窗口中,则需要重新绘制屏幕 */ if (dsp_ctx.window.topline == dsp_ctx.buffer.topline) erase_upward_console_screen(dsp_ctx.buffer.topline); } /* 复制一行数据至缓存,行以输入的"\n"界定 */ pos = cp_to_buffer(buffer); if (pos == strlen(buffer)) { break; } buffer = (char*)((unsigned long)buffer + pos); } /* 第二步,向屏幕输出,更新屏幕状态 */ /* 如果当前屏幕处在buf的末端,向屏幕打印新输入的字符串 并滚动 如果当前屏幕处于回滚状态 正在显示之前的内容,则不向屏幕打印新写入的数据 */ if (dsp_ctx.window.downward == 0) { /* 向屏幕打印新写入的数据,直到打印到最后一个字符 */ while (dsp_ctx.window.lastchar != dsp_ctx.buffer.lastchar) { /* 屏幕满,向上滚动 */ if (dsp_ctx.window.pos_y >= dsp_ctx.max_y - 20) { erase_upward_console_screen(dsp_ctx.window.step[0]); } /* 屏幕不满时一行行输出 */ else { /*打印一行(指屏幕)数据,或者不足一行时打印到缓存最后一个字符 count为本次处理的字节数 */ count = draw_a_line(&dsp_ctx.window.pos_x, &dsp_ctx.window.pos_y, dsp_ctx.window.lastchar, dsp_ctx.buffer.lastchar); /* 更新窗口的状态 */ dsp_ctx.window.lastchar = get_buf_idx(dsp_ctx.window.lastchar + count); modify_up_idx(dsp_ctx.window.pos_x, dsp_ctx.window.pos_y); } } } spin_unlock_irqrestore(&dsp_ctx.lock, flags); ret: return; }
/* 屏幕向下滚动 注意,此函数不是接口,实现这个功能还需要在外面包一层 目前接口还未实现,因为目前还不具备所需的条件 */ static void erase_dnward_console_screen(int step) { int pos_x, pos_y; int i; unsigned long newline, erased_line; unsigned long erased_count, count; int erased_pos_x = 0; int erased_pos_y = 0; int new_pos_x = 0; int new_pos_y = 0; /* 当前已经是第一行,直接退出 */ if (dsp_ctx.window.topline == dsp_ctx.buffer.topline) { return; } reset_up_idx(); erased_line = dsp_ctx.window.topline; /* 定位屏幕应输出的第一行 */ newline = erased_line; for (i = 0; i < step; i++) { newline = prev_line_in_buffer(newline); if (newline == dsp_ctx.buffer.topline) break; } dsp_ctx.window.topline = newline; /* 刷新屏幕,每次循环刷新一行 从屏幕左上角开始刷新 */ while (1) { if (erased_line != dsp_ctx.buffer.lastchar) { dsp_ctx.color = BLACK_PIX; /* 用黑色重写本行,即擦除本行 */ erased_count = draw_a_line(&erased_pos_x, &erased_pos_y, erased_line, dsp_ctx.buffer.lastchar); erased_line = get_buf_idx(erased_line + erased_count); } /* 向屏幕打印需输出的行 */ dsp_ctx.color = WHITE_PIX; count = draw_a_line(&new_pos_x, &new_pos_y, newline, dsp_ctx.buffer.lastchar); dsp_ctx.window.lastchar = get_buf_idx(newline + count); newline = get_buf_idx(newline + count); /* 新数据已经输出到缓存末尾 */ if (newline == dsp_ctx.buffer.lastchar) break; modify_up_idx(new_pos_x, new_pos_y); /* 已打印满一屏 */ if (new_pos_y >= (dsp_ctx.max_y - 20)) break; } dsp_ctx.window.downward = 1; dsp_ctx.window.pos_x = new_pos_x; dsp_ctx.window.pos_y = new_pos_y; dsp_ctx.color = WHITE_PIX; return; }