60.html
来自「linux 0.11中文版 有注释」· HTML 代码 · 共 725 行 · 第 1/5 页
HTML
725 行
<a name='L103'><b>static</b> <b>unsigned</b> <b>long</b> origin; <i><font color='green'>/* Used for EGA/VGA fast scroll */</font></i><i><font color='green'>// scr_start。</font></i>
<a name='L104'><i><font color='green'>/* 用于EGA/VGA 快速滚屏 */</font></i><i><font color='green'>// 滚屏起始内存地址。</font></i>
<a name='L105'><b>static</b> <b>unsigned</b> <b>long</b> scr_end; <i><font color='green'>/* Used for EGA/VGA fast scroll */</font></i>
<a name='L106'><i><font color='green'>/* 用于EGA/VGA 快速滚屏 */</font></i><i><font color='green'>// 滚屏末端内存地址。</font></i>
<a name='L107'><b>static</b> <b>unsigned</b> <b>long</b> <a href='../D/915.html' title='Multiple defined in 9 places.'>pos</a>; <i><font color='green'>// 当前光标对应的显示内存位置。</font></i>
<a name='L108'><b>static</b> <b>unsigned</b> <b>long</b> x, y; <i><font color='green'>// 当前光标位置。</font></i>
<a name='L109'><b>static</b> <b>unsigned</b> <b>long</b> top, bottom; <i><font color='green'>// 滚动时顶行行号;底行行号。</font></i>
<a name='L110'><i><font color='green'>// state 用于标明处理ESC 转义序列时的当前步骤。npar,par[]用于存放ESC 序列的中间处理参数。</font></i>
<a name='L111'><b>static</b> <b>unsigned</b> <b>long</b> state = 0; <i><font color='green'>// ANSI 转义字符序列处理状态。</font></i>
<a name='L112'><b>static</b> <b>unsigned</b> <b>long</b> npar, par[<a href='../S/60.html#L77' title='Defined at 77 in kernel/chr_drv/console.c.'>NPAR</a>]; <i><font color='green'>// ANSI 转义字符序列参数个数和参数数组。</font></i>
<a name='L113'><b>static</b> <b>unsigned</b> <b>long</b> ques = 0;
<a name='L114'><b>static</b> <b>unsigned</b> <b>char</b> attr = 0x07; <i><font color='green'>// 字符属性(黑底白字)。</font></i>
<a name='L115'>
<a name='L116'><b>static</b> <b>void</b> <a href='../S/60.html#L978' title='Defined at 978 in kernel/chr_drv/console.c.'>sysbeep</a> (<b>void</b>); <i><font color='green'>// 系统蜂鸣函数。</font></i>
<a name='L117'>
<a name='L118'><i><font color='green'>/*</font></i>
<a name='L119'><i><font color='green'>* this is what the terminal answers to a ESC-Z or csi0c</font></i>
<a name='L120'><i><font color='green'>* query (= vt100 response).</font></i>
<a name='L121'><i><font color='green'>*/</font></i>
<a name='L122'><i><font color='green'>/*</font></i>
<a name='L123'><i><font color='green'>* 下面是终端回应ESC-Z 或csi0c 请求的应答(=vt100 响应)。</font></i>
<a name='L124'><i><font color='green'>*/</font></i>
<a name='L125'><i><font color='green'>// csi - 控制序列引导码(Control Sequence Introducer)。</font></i>
<a name='L126'><font color='darkred'>#define</font> <a href='../S/60.html#L439' title='Refered from 439 in kernel/chr_drv/console.c.'>RESPONSE</a> "\033[?1;2c"
<a name='L127'>
<a name='L128'><i><font color='green'>/* NOTE! gotoxy thinks x==video_num_columns is ok */</font></i>
<a name='L129'><i><font color='green'>/* 注意!gotoxy 函数认为x==video_num_columns,这是正确的 */</font></i>
<a name='L130'><i><font color='green'>//// 跟踪光标当前位置。</font></i>
<a name='L131'><i><font color='green'>// 参数:new_x - 光标所在列号;new_y - 光标所在行号。</font></i>
<a name='L132'><i><font color='green'>// 更新当前光标位置变量x,y,并修正pos 指向光标在显示内存中的对应位置。</font></i>
<a name='L133'><b>static</b> <b>inline</b> <b>void</b>
<a name='L134'><a href='../R/492.html' title='Multiple refered from 12 places.'>gotoxy</a> (<b>unsigned</b> <b>int</b> new_x, <b>unsigned</b> <b>int</b> new_y)
<a name='L135'><font color='red'>{</font>
<a name='L136'><i><font color='green'>// 如果输入的光标行号超出显示器列数,或者光标行号超出显示的最大行数,则退出。</font></i>
<a name='L137'> <b>if</b> (new_x > video_num_columns || new_y >= video_num_lines)
<a name='L138'> <b>return</b>;
<a name='L139'><i><font color='green'>// 更新当前光标变量;更新光标位置对应的在显示内存中位置变量pos。</font></i>
<a name='L140'> x = new_x;
<a name='L141'> y = new_y;
<a name='L142'> <a href='../D/915.html' title='Multiple defined in 9 places.'>pos</a> = origin + y * video_size_row + (x << 1);
<a name='L143'><font color='red'>}</font>
<a name='L144'>
<a name='L145'><i><font color='green'>//// 设置滚屏起始显示内存地址。</font></i>
<a name='L146'><b>static</b> <b>inline</b> <b>void</b>
<a name='L147'><a href='../S/60.html#L208' title='Refered from 208 in kernel/chr_drv/console.c.'>set_origin</a> (<b>void</b>)
<a name='L148'><font color='red'>{</font>
<a name='L149'> <a href='../S/25.html#L15' title='Defined at 15 in include/asm/system.h.'>cli</a> ();
<a name='L150'><i><font color='green'>// 首先选择显示控制数据寄存器r12,然后写入卷屏起始地址高字节。向右移动9 位,表示向右移动</font></i>
<a name='L151'><i><font color='green'>// 8 位,再除以2(2 字节代表屏幕上1 字符)。是相对于默认显示内存操作的。</font></i>
<a name='L152'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (12, video_port_reg);
<a name='L153'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (0xff & ((origin - video_mem_start) >> 9), video_port_val);
<a name='L154'><i><font color='green'>// 再选择显示控制数据寄存器r13,然后写入卷屏起始地址底字节。向右移动1 位表示除以2。</font></i>
<a name='L155'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (13, video_port_reg);
<a name='L156'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (0xff & ((origin - video_mem_start) >> 1), video_port_val);
<a name='L157'> <a href='../S/25.html#L14' title='Defined at 14 in include/asm/system.h.'>sti</a> ();
<a name='L158'><font color='red'>}</font>
<a name='L159'>
<a name='L160'><i><font color='green'>//// 向上卷动一行(屏幕窗口向下移动)。</font></i>
<a name='L161'><i><font color='green'>// 将屏幕窗口向下移动一行。参见程序列表后说明。</font></i>
<a name='L162'><b>static</b> <b>void</b>
<a name='L163'><a href='../R/588.html' title='Multiple refered from 2 places.'>scrup</a> (<b>void</b>)
<a name='L164'><font color='red'>{</font>
<a name='L165'><i><font color='green'>// 如果显示类型是EGA,则执行以下操作。</font></i>
<a name='L166'> <b>if</b> (video_type == <a href='../S/60.html#L75' title='Defined at 75 in kernel/chr_drv/console.c.'>VIDEO_TYPE_EGAC</a> || video_type == <a href='../S/60.html#L74' title='Defined at 74 in kernel/chr_drv/console.c.'>VIDEO_TYPE_EGAM</a>)
<a name='L167'> <font color='red'>{</font>
<a name='L168'><i><font color='green'>// 如果移动起始行top=0,移动最底行bottom=video_num_lines=25,则表示整屏窗口向下移动。</font></i>
<a name='L169'> <b>if</b> (!top && bottom == video_num_lines)
<a name='L170'> <font color='red'>{</font>
<a name='L171'><i><font color='green'>// 调整屏幕显示对应内存的起始位置指针origin 为向下移一行屏幕字符对应的内存位置,同时也调整</font></i>
<a name='L172'><i><font color='green'>// 当前光标对应的内存位置以及屏幕末行末端字符指针scr_end 的位置。</font></i>
<a name='L173'> origin += video_size_row;
<a name='L174'> <a href='../D/915.html' title='Multiple defined in 9 places.'>pos</a> += video_size_row;
<a name='L175'> scr_end += video_size_row;
<a name='L176'><i><font color='green'>// 如果屏幕末端最后一个显示字符所对应的显示内存指针scr_end 超出了实际显示内存的末端,则将</font></i>
<a name='L177'><i><font color='green'>// 屏幕内容内存数据移动到显示内存的起始位置video_mem_start 处,并在出现的新行上填入空格字符。</font></i>
<a name='L178'> <b>if</b> (scr_end > video_mem_end)
<a name='L179'> <font color='red'>{</font>
<a name='L180'><i><font color='green'>// %0 - eax(擦除字符+属性);%1 - ecx((显示器字符行数-1)所对应的字符数/2,是以长字移动);</font></i>
<a name='L181'><i><font color='green'>// %2 - edi(显示内存起始位置video_mem_start);%3 - esi(屏幕内容对应的内存起始位置origin)。</font></i>
<a name='L182'><i><font color='green'>// 移动方向:[edi]??[esi],移动ecx 个长字。</font></i>
<a name='L183'> <b>__asm__</b> ("cld\n\t" <i><font color='green'>// 清方向位。</font></i>
<a name='L184'> "rep\n\t" <i><font color='green'>// 重复操作,将当前屏幕内存数据</font></i>
<a name='L185'> "movsl\n\t" <i><font color='green'>// 移动到显示内存起始处。</font></i>
<a name='L186'> "movl _video_num_columns,%1\n\t" <i><font color='green'>// ecx=1 行字符数。</font></i>
<a name='L187'> "rep\n\t" <i><font color='green'>// 在新行上填入空格字符。</font></i>
<a name='L188'> "stosw"::"a" (video_erase_char), "c" ((video_num_lines - 1) * video_num_columns >> 1), "D" (video_mem_start), "S" (origin):"cx", "di",
<a name='L189'> "si");
<a name='L190'><i><font color='green'>// 根据屏幕内存数据移动后的情况,重新调整当前屏幕对应内存的起始指针、光标位置指针和屏幕末端</font></i>
<a name='L191'><i><font color='green'>// 对应内存指针scr_end。</font></i>
<a name='L192'> scr_end -= origin - video_mem_start;
<a name='L193'> <a href='../D/915.html' title='Multiple defined in 9 places.'>pos</a> -= origin - video_mem_start;
<a name='L194'> origin = video_mem_start;
<a name='L195'> <font color='red'>}</font>
<a name='L196'> <b>else</b>
<a name='L197'> <font color='red'>{</font>
<a name='L198'><i><font color='green'>// 如果调整后的屏幕末端对应的内存指针scr_end 没有超出显示内存的末端video_mem_end,则只需在</font></i>
<a name='L199'><i><font color='green'>// 新行上填入擦除字符(空格字符)。</font></i>
<a name='L200'><i><font color='green'>// %0 - eax(擦除字符+属性);%1 - ecx(显示器字符行数);%2 - edi(屏幕对应内存最后一行开始处);</font></i>
<a name='L201'> <b>__asm__</b> ("cld\n\t" <i><font color='green'>// 清方向位。</font></i>
<a name='L202'> "rep\n\t" <i><font color='green'>// 重复操作,在新出现行上</font></i>
<a name='L203'> "stosw" <i><font color='green'>// 填入擦除字符(空格字符)。</font></i>
<a name='L204'> ::"a" (video_erase_char), "c" (video_num_columns), "D" (scr_end - video_size_row):"cx",
<a name='L205'> "di");
<a name='L206'> <font color='red'>}</font>
<a name='L207'><i><font color='green'>// 向显示控制器中写入新的屏幕内容对应的内存起始位置值。</font></i>
<a name='L208'> <a href='../S/60.html#L147' title='Defined at 147 in kernel/chr_drv/console.c.'>set_origin</a> ();
<a name='L209'><i><font color='green'>// 否则表示不是整屏移动。也即表示从指定行top 开始的所有行向上移动1 行(删除1 行)。此时直接</font></i>
<a name='L210'><i><font color='green'>// 将屏幕从指定行top 到屏幕末端所有行对应的显示内存数据向上移动1 行,并在新出现的行上填入擦</font></i>
<a name='L211'><i><font color='green'>// 除字符。</font></i>
<a name='L212'><i><font color='green'>// %0-eax(擦除字符+属性);%1-ecx(top 行下1 行开始到屏幕末行的行数所对应的内存长字数);</font></i>
<a name='L213'><i><font color='green'>// %2-edi(top 行所处的内存位置);%3-esi(top+1 行所处的内存位置)。</font></i>
<a name='L214'> <font color='red'>}</font>
<a name='L215'> <b>else</b>
<a name='L216'> <font color='red'>{</font>
<a name='L217'> <b>__asm__</b> ("cld\n\t" <i><font color='green'>// 清方向位。</font></i>
<a name='L218'> "rep\n\t" <i><font color='green'>// 循环操作,将top+1 到bottom 行</font></i>
<a name='L219'> "movsl\n\t" <i><font color='green'>// 所对应的内存块移到top 行开始处。</font></i>
<a name='L220'> "movl _video_num_columns,%%ecx\n\t" <i><font color='green'>// ecx = 1 行字符数。</font></i>
<a name='L221'> "rep\n\t" <i><font color='green'>// 在新行上填入擦除字符。</font></i>
<a name='L222'> "stosw"::"a" (video_erase_char), "c" ((bottom - top - 1) * video_num_columns >> 1), "D" (origin + video_size_row * top), "S" (origin + video_size_row * (top + 1)):"cx", "di",
<a name='L223'> "si");
<a name='L224'> <font color='red'>}</font>
<a name='L225'> <font color='red'>}</font>
<a name='L226'><i><font color='green'>// 如果显示类型不是EGA(是MDA),则执行下面移动操作。因为MDA 显示控制卡会自动调整超出显示范围</font></i>
<a name='L227'><i><font color='green'>// 的情况,也即会自动翻卷指针,所以这里不对屏幕内容对应内存超出显示内存的情况单独处理。处理</font></i>
<a name='L228'><i><font color='green'>// 方法与EGA 非整屏移动情况完全一样。</font></i>
<a name='L229'> <b>else</b> <i><font color='green'>/* Not EGA/VGA */</font></i>
<a name='L230'> <font color='red'>{</font>
<a name='L231'> <b>__asm__</b> ("cld\n\t" "rep\n\t" "movsl\n\t" "movl _video_num_columns,%%ecx\n\t" "rep\n\t" "stosw"::"a" (video_erase_char), "c" ((bottom - top - 1) * video_num_columns >> 1), "D" (origin + video_size_row * top), "S" (origin + video_size_row * (top + 1)):"cx", "di",
<a name='L232'> "si");
<a name='L233'> <font color='red'>}</font>
<a name='L234'><font color='red'>}</font>
<a name='L235'>
<a name='L236'><i><font color='green'>//// 向下卷动一行(屏幕窗口向上移动)。</font></i>
<a name='L237'><i><font color='green'>// 将屏幕窗口向上移动一行,屏幕显示的内容向下移动1 行,在被移动开始行的上方出现一新行。参见</font></i>
<a name='L238'><i><font color='green'>// 程序列表后说明。处理方法与scrup()相似,只是为了在移动显示内存数据时不出现数据覆盖错误情</font></i>
<a name='L239'><i><font color='green'>// 况,复制是以反方向进行的,也即从屏幕倒数第2 行的最后一个字符开始复制</font></i>
<a name='L240'><b>static</b> <b>void</b>
<a name='L241'><a href='../R/587.html' title='Multiple refered from 2 places.'>scrdown</a> (<b>void</b>)
<a name='L242'><font color='red'>{</font>
<a name='L243'><i><font color='green'>// 如果显示类型是EGA,则执行下列操作。</font></i>
<a name='L244'><i><font color='green'>// [??好象if 和else 的操作完全一样啊!为什么还要分别处理呢?难道与任务切换有关?]</font></i>
<a name='L245'> <b>if</b> (video_type == <a href='../S/60.html#L75' title='Defined at 75 in kernel/chr_drv/console.c.'>VIDEO_TYPE_EGAC</a> || video_type == <a href='../S/60.html#L74' title='Defined at 74 in kernel/chr_drv/console.c.'>VIDEO_TYPE_EGAM</a>)
<a name='L246'> <font color='red'>{</font>
<a name='L247'><i><font color='green'>// %0-eax(擦除字符+属性);%1-ecx(top 行开始到屏幕末行-1 行的行数所对应的内存长字数);</font></i>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?