Changeset 17948 for trunk/termtv/js


Ignore:
Timestamp:
08/08/14 09:24:18 (10 years ago)
Author:
tbretz
Message:
Replaced octal characters with hex-characters to avoid clashes with the strict language standard.
Location:
trunk/termtv/js
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/termtv/js/parser.js

    r17409 r17948  
    9292    // in the loop over the handlabels, but maybe a sequence
    9393    // ot split into to chunks.
    94     if (this.buffer.length>50 && this.buffer[0]=='\033')
     94    if (this.buffer.length>50 && this.buffer[0]=='\x1b')
    9595    {
    9696        this.debug("Unknown escape sequence: "+
     
    123123
    124124    // ascii // Everything except escape, special chars and 1xxxx xxxx
    125     // was: [/^[^\033\007\010\011\012\013\014\015\016\017\x80-\xFF]?/,
     125    // was: [/^[^\x1b\007\010\011\012\013\014\015\016\017\x80-\xFF]?/,
    126126    [/^[\x20-\x7F]+/, function (m) {
    127127        this.emu.ev_normalString(m[0]);
     
    147147    ////////////////////////////////////////////////////////////////////////////////
    148148    // attributes (colors)
    149     [/^\033\[([0-9;]*)m/, function (m) {
     149    [/^\x1b\[([0-9;]*)m/, function (m) {
    150150        this.emu.ev_setAttribute(m[1].split(';'));
    151151    }],
     
    192192    ////////////////////////////////////////////////////////////////////////////////
    193193    // control characters
    194     [/^\007/, function (m) {
     194    [/^\x07/, function (m) {
    195195        this.emu.ev_specialChar('bell');
    196196    }],
    197     [/^\010/, function (m) {
     197    [/^\x08/, function (m) {
    198198        this.emu.ev_specialChar('backspace');
    199199    }],
    200     [/^\011/, function (m) {
     200    [/^\x09/, function (m) {
    201201        this.emu.ev_specialChar('horizontalTab');
    202202    }],
    203     [/^\012/, function (m) {
     203    [/^\x0a/, function (m) {
    204204        this.emu.ev_specialChar('lineFeed');
    205205    }],
    206     [/^\013/, function (m) {
     206    [/^\x0b/, function (m) {
    207207        this.emu.ev_specialChar('verticalTab');
    208208    }],
    209     [/^\014/, function (m) {
     209    [/^\x0c/, function (m) {
    210210        this.emu.ev_specialChar('formFeed');
    211211    }],
    212     [/^\015/, function (m) {
     212    [/^\x0d/, function (m) {
    213213        this.emu.ev_specialChar('carriageReturn');
    214214    }],
    215     [/^\016/, function (m) {
     215    [/^\x0e/, function (m) {
    216216        this.emu.ev_switchCharset('g1');
    217217    }],
    218     [/^\017/, function (m) {
     218    [/^\x0f/, function (m) {
    219219        this.emu.ev_switchCharset('g0');
    220220    }],
    221221
    222     [/^\033F/, function (m) { // vt52: enter graphics mode
     222    [/^\x1bF/, function (m) { // vt52: enter graphics mode
    223223        //this.emu.ev_switchCharset('g0', 'line');
    224224    }],
    225     [/^\033G/, function (m) { // vt52: exit graphics mode
     225    [/^\x1bG/, function (m) { // vt52: exit graphics mode
    226226        //this.emu.ev_switchCharset('g0', 'us');
    227227    }],
     
    231231    // very often used: home and goto
    232232
    233     [/^\033\[[Hf]/, function (m) {
     233    [/^\x1b\[[Hf]/, function (m) {
    234234        this.emu.ev_goto( 1, 1 );
    235235    }],
    236     [/^\033\[([0-9]*)G/, function (m) {
     236    [/^\x1b\[([0-9]*)G/, function (m) {
    237237        this.emu.ev_goto(parseInt(m[1] || '1', 10), -1);  // y=-1 (keep line)
    238238    }],
    239239
    240240    // cursor set position
    241     [/^\033\[([0-9]*);([0-9]*)[Hf]/, function (m) {
     241    [/^\x1b\[([0-9]*);([0-9]*)[Hf]/, function (m) {
    242242        this.emu.ev_goto(parseInt(m[2] || '1', 10), parseInt(m[1] || '1', 10));
    243243    }],
    244     [/^\033\[([0-9]*)d/, function (m) {
     244    [/^\x1b\[([0-9]*)d/, function (m) {
    245245        this.emu.ev_goto(1, parseInt(m[1] || '1', 10));
    246246
     
    250250    // obsolete control characters
    251251
    252     [/^[\000-\006]/, function() { } ],
    253     [/^[\020-\032]/, function() { } ],
    254     [/^[\034-\037]/, function() { } ],
     252    [/^[\x00-\x06]/, function() { } ],
     253    [/^[\x10-\x1a]/, function() { } ],
     254    [/^[\x1c-\x1f]/, function() { } ],
    255255/*
    256256    [/^\000/, function (m) {
     
    326326
    327327    // erase in line
    328     [/^\033\[0?K/, function (m) {
     328    [/^\x1b\[0?K/, function (m) {
    329329        this.emu.ev_eraseInLine('toEnd');
    330330    }],
    331     [/^\033\[1K/, function (m) {
     331    [/^\x1b\[1K/, function (m) {
    332332        this.emu.ev_eraseInLine('toStart');
    333333    }],
    334     [/^\033\[2K/, function (m) {
     334    [/^\x1b\[2K/, function (m) {
    335335        this.emu.ev_eraseInLine('whole');
    336336    }],
    337     [/^\033K/, function (m) { // vt52
     337    [/^\x1bK/, function (m) { // vt52
    338338        this.emu.ev_eraseInLine('toEnd');
    339339    }],
    340340
    341341    // erase in display
    342     [/^\033\[0?J/, function (m) {
     342    [/^\x1b\[0?J/, function (m) {
    343343        this.emu.ev_eraseInDisplay('toEnd');
    344344    }],
    345     [/^\033\[1J/, function (m) {
     345    [/^\x1b\[1J/, function (m) {
    346346        this.emu.ev_eraseInDisplay('toStart');
    347347    }],
    348     [/^\033\[2J/, function (m) {
     348    [/^\x1b\[2J/, function (m) {
    349349        this.emu.ev_eraseInDisplay('whole');
    350350    }],
    351     [/^\033J/, function (m) { // vt52
     351    [/^\x1bJ/, function (m) { // vt52
    352352        this.emu.ev_eraseInDisplay('toEnd');
    353353    }],
    354354
    355355    // insertion and deletion
    356     [/^\033\[([0-9]*)P/, function (m) {
     356    [/^\x1b\[([0-9]*)P/, function (m) {
    357357        this.emu.ev_deleteChars(parseInt(m[1] || '1', 10));
    358358    }],
    359     [/^\033\[([0-9]*)X/, function (m) {
     359    [/^\x1b\[([0-9]*)X/, function (m) {
    360360        this.emu.ev_deleteChars(parseInt(m[1] || '1', 10));
    361361    }],
    362     [/^\033\[([0-9]*)L/, function (m) {
     362    [/^\x1b\[([0-9]*)L/, function (m) {
    363363        this.emu.ev_insertLines(parseInt(m[1] ||'1', 10));
    364364    }],
    365     [/^\033\[([0-9]*)M/, function (m) {
     365    [/^\x1b\[([0-9]*)M/, function (m) {
    366366        this.emu.ev_deleteLines(parseInt(m[1] || '1', 10));
    367367    }],
    368     [/^\033\[([0-9])*@/, function (m) { // insert N characters
     368    [/^\x1b\[([0-9])*@/, function (m) { // insert N characters
    369369       this.emu.ev_insertChars(parseInt(m[1] || '1', 10));
    370370       //this.emu.ev_mode('insertLimited', parseInt(m[1] || '1', 10));
     
    372372
    373373    // margins
    374     [/^\033\[([0-9]+);([0-9]+)r/, function (m) {
     374    [/^\x1b\[([0-9]+);([0-9]+)r/, function (m) {
    375375        this.emu.ev_setMargins(parseInt(m[1], 10), parseInt(m[2], 10));
    376376    }],
    377     [/^\033\[r/, function (m) {
     377    [/^\x1b\[r/, function (m) {
    378378        this.emu.ev_resetMargins();
    379379    }],
     
    385385    // 6: overline (eterm)
    386386    // 9: strikeout (gnome, guake, nautilus, terminator, xfce4, vte)
    387     [/^\033\[\[([0-9;]*)m/, function (m) {
     387    [/^\x1b\[\[([0-9;]*)m/, function (m) {
    388388    }],
    389389
    390390
    391391    // arrow keys
    392     [/^\033\[([0-9]*)A/, function (m) {
     392    [/^\x1b\[([0-9]*)A/, function (m) {
    393393        this.emu.ev_arrow('up', parseInt(m[1] || '1', 10));
    394394    }],
    395     [/^\033\[([0-9]*)B/, function (m) {
     395    [/^\x1b\[([0-9]*)B/, function (m) {
    396396        this.emu.ev_arrow('down', parseInt(m[1] || '1', 10));
    397397    }],
    398     [/^\033\[([0-9]*)C/, function (m) {
     398    [/^\x1b\[([0-9]*)C/, function (m) {
    399399        this.emu.ev_arrow('right', parseInt(m[1] || '1', 10));
    400400    }],
    401     [/^\033\[([0-9]*)D/, function (m) {
     401    [/^\x1b\[([0-9]*)D/, function (m) {
    402402        this.emu.ev_arrow('left', parseInt(m[1] || '1', 10));
    403403    }],
    404     [/^\033\[([0-9]*)E/, function (m) {
     404    [/^\x1b\[([0-9]*)E/, function (m) {
    405405        this.emu.ev_index('nextLine', parseInt(m[1] || '1', 10));
    406406    }],
    407     [/^\033\[([0-9]*)F/, function (m) {
     407    [/^\x1b\[([0-9]*)F/, function (m) {
    408408        this.emu.ev_index('prevLine', parseInt(m[1] || '1', 10));
    409409    }],
    410410
    411     [/^\033A([\x20-\x7F]?)/, function (m) {  // vt52
     411    [/^\x1bA([\x20-\x7F]?)/, function (m) {  // vt52
    412412        this.emu.ev_arrow('up', m[1] ? m[1].charCodeAt(0)-32+1 : 1);
    413413    }],
    414     [/^\033B([\x20-\x7F]?)/, function (m) {  // vt52
     414    [/^\x1bB([\x20-\x7F]?)/, function (m) {  // vt52
    415415        this.emu.ev_arrow('down', m[1] ? m[1].charCodeAt(0)-32+1 : 1);
    416416    }],
    417     [/^\033C([\x20-\x7F]?)/, function (m) {  // vt52
     417    [/^\x1bC([\x20-\x7F]?)/, function (m) {  // vt52
    418418        this.emu.ev_arrow('right', m[1] ? m[1].charCodeAt(0)-32+1 : 1);
    419419    }],
    420     [/^\033D/, function (m) {  // vt52
     420    [/^\x1bD/, function (m) {  // vt52
    421421        this.emu.ev_arrow('left', 1);
    422422    }],
    423     [/^\033Y(..)/, function (m) { // vt52
     423    [/^\x1bY(..)/, function (m) { // vt52
    424424        this.emu.ev_goto(m[1].charCodeAt(1)-32+1, m[1].charCodeAt(0)-32+1);
    425425    }],
    426426
    427     // vt52: \033I reverse line feed
    428     // \033l  move to first line (keep x)
     427    // vt52: \x1bI reverse line feed
     428    // \x1bl  move to first line (keep x)
    429429
    430430    // cursor to lower left corner (vt100)
    431     //[/^\033F/, function (m) {
     431    //[/^\x1bF/, function (m) {
    432432    //}],
    433433
    434     // \033[{n}Z  cursor back tab
    435     // \033[{n}I  cursor horizontal tab
    436     // \033[{n}W  cursor tab stop control
    437     // \033[{n}Y  cursor vertical tab
    438     // \033[{n}P  delete character
    439     // \033#8     screen alignment display
    440     // \033[H     horizontal tab stop
     434    // \x1b[{n}Z  cursor back tab
     435    // \x1b[{n}I  cursor horizontal tab
     436    // \x1b[{n}W  cursor tab stop control
     437    // \x1b[{n}Y  cursor vertical tab
     438    // \x1b[{n}P  delete character
     439    // \x1b#8     screen alignment display
     440    // \x1b[H     horizontal tab stop
    441441
    442442
    443443    // index and friends
    444     [/^\033D/, function (m) {
     444    [/^\x1bD/, function (m) {
    445445        this.emu.ev_index('down', 1);
    446446    }],
    447     [/^\033M/, function (m) {
     447    [/^\x1bM/, function (m) {
    448448        this.emu.ev_index('up', 1);
    449449    }],
    450     [/^\033E/, function (m) {
     450    [/^\x1bE/, function (m) {
    451451        this.emu.ev_index('nextLine', 1);
    452452    }],
    453453
    454454
    455     // \033[6] back index
    456     // \033[9] forward index
     455    // \x1b[6] back index
     456    // \x1b[9] forward index
    457457
    458458    // cursor save/restore
     
    464464    //         state of origin mode
    465465    //         state of selective erase
    466     [/^\033[7]/, function (m) {
     466    [/^\x1b[7]/, function (m) {
    467467        this.emu.ev_cursorStack('push', true);
    468468    }],
    469     [/^\033[8]/, function (m) {
     469    [/^\x1b[8]/, function (m) {
    470470        this.emu.ev_cursorStack('pop', true);
    471471    }],
    472472    // cursor save/restore position only
    473     [/^\033\[s/, function (m) {
     473    [/^\x1b\[s/, function (m) {
    474474        this.emu.ev_cursorStack('push', false);
    475475    }],
    476     [/^\033\[u/, function (m) {
     476    [/^\x1b\[u/, function (m) {
    477477        this.emu.ev_cursorStack('pop', false);
    478478    }],
    479479
    480480    // keypad
    481     [/^\033=/, function (m) {
     481    [/^\x1b=/, function (m) {
    482482        this.emu.ev_mode('keypad', 'cursor');
    483483    }],
    484     [/^\033>/, function (m) {
     484    [/^\x1b>/, function (m) {
    485485        this.emu.ev_mode('keypad', 'numeric');
    486486    }],
    487487
    488488    // mode set/reset
    489     //[/^\033\[(\??)([^\033]*?)h/, function (m) {
    490     [/^\033\[(\??)([0-9;]+)h/, function (m) {
     489    //[/^\x1b\[(\??)([^\x1b]*?)h/, function (m) {
     490    [/^\x1b\[(\??)([0-9;]+)h/, function (m) {
    491491        var me = this;
    492492        m[2].split(';').forEach(function (sub) {
     
    494494            });
    495495    }],
    496     //[/^\033\[(\??)([^\033]*?)l/, function (m) {
    497     [/^\033\[(\??)([0-9;]+)l/, function (m) {
     496    //[/^\x1b\[(\??)([^\x1b]*?)l/, function (m) {
     497    [/^\x1b\[(\??)([0-9;]+)l/, function (m) {
    498498        var me = this;
    499499        m[2].split(';').forEach(function (sub) {
     
    502502    }],
    503503
    504     // curser layout;  '\033[?17;0;0c' hide cursor
    505     [/^\033\[\?([0-9;]*)c/, function (m) {
     504    // curser layout;  '\x1b[?17;0;0c' hide cursor
     505    [/^\x1b\[\?([0-9;]*)c/, function (m) {
    506506        this.debug("cursor layout"+m[1]);
    507507    }],
    508508
    509509    // horizontal tab stops
    510     [/^\033H/, function (m) {
     510    [/^\x1bH/, function (m) {
    511511        //this.emu.ev_tabStop('add');    // set a tab stop at the current position
    512512        this.emu.ev_goto( 1, 1);    // vt52: home
    513513    }],
    514     [/^\033\[0?g/, function (m) {
     514    [/^\x1b\[0?g/, function (m) {
    515515        this.emu.ev_tabStop('remove'); // clear tabs at the current position
    516516    }],
    517     [/^\033\[3g/, function (m) {
     517    [/^\x1b\[3g/, function (m) {
    518518        this.emu.ev_tabStop('clear');  // clear all tab stops
    519519    }],
    520520
    521521    // line attributes
    522     [/^\033#3/, function (m) {
     522    [/^\x1b#3/, function (m) {
    523523        this.emu.ev_lineAttr('dwdhTopHalf');
    524524    }],
    525     [/^\033#4/, function (m) {
     525    [/^\x1b#4/, function (m) {
    526526        this.emu.ev_lineAttr('dwdhBottomHalf');
    527527    }],
    528     [/^\033#5/, function (m) {
     528    [/^\x1b#5/, function (m) {
    529529        this.emu.ev_lineAttr('swsh');
    530530    }],
    531     [/^\033#6/, function (m) {
     531    [/^\x1b#6/, function (m) {
    532532        this.emu.ev_lineAttr('dwsh');
    533533    }],
    534534
    535535    // erase in area
    536     // \033\[0?K    toEnd
    537     // \033\[1K     toStart
    538     // \033\[2K     whole
     536    // \x1b\[0?K    toEnd
     537    // \x1b\[1K     toStart
     538    // \x1b\[2K     whole
    539539
    540540    // erase in field
    541     // \033\[0?N    toEnd
    542     // \033\[1N     toStart
    543     // \033\[2N     whole
     541    // \x1b\[0?N    toEnd
     542    // \x1b\[1N     toStart
     543    // \x1b\[2N     whole
    544544
    545545    // erase character
    546     // \033[{N}X
    547 
    548     // \033[{N}T scroll down
    549     // \033[{N}S scroll up
    550 
    551 
    552     // There is \033[?...J as well (erase "selective" in display)
    553     // There is \033[?...K as well (erase "selective" in line)
    554 
    555     // \033V Start of guarded area
    556     // \033W End of guarded area
    557 
    558     // \033l Lock memory above cursor
    559     // \033m Unlock memory above cursor
     546    // \x1b[{N}X
     547
     548    // \x1b[{N}T scroll down
     549    // \x1b[{N}S scroll up
     550
     551
     552    // There is \x1b[?...J as well (erase "selective" in display)
     553    // There is \x1b[?...K as well (erase "selective" in line)
     554
     555    // \x1bV Start of guarded area
     556    // \x1bW End of guarded area
     557
     558    // \x1bl Lock memory above cursor
     559    // \x1bm Unlock memory above cursor
    560560
    561561    // reset
    562     [/^\033\[!p/, function (m) {
     562    [/^\x1b\[!p/, function (m) {
    563563        this.emu.ev_softReset();
    564564    }],
    565     [/^\033c/, function (m) {
     565    [/^\x1bc/, function (m) {
    566566        this.emu.ev_reset();
    567567    }],
    568568
    569569    // resize terminal: \e[8;{height};{width}t
    570     [/^\033\[([0-9;]*)t/, function (m) {
     570    [/^\x1b\[([0-9;]*)t/, function (m) {
    571571    }],
    572572
    573573    // xterm-style titles
    574     [/^\033\]2;([^\033\007]*)\007/, function (m) {
     574    [/^\x1b\]2;([^\x1b\x07]*)\x07/, function (m) {
    575575        this.emu.ev_setWindowTitle(m[1]);
    576576    }],
    577     [/^\033\]1;([^\033\007]*)\007/, function (m) {
     577    [/^\x1b\]1;([^\x1b\x07]*)\x07/, function (m) {
    578578        this.emu.ev_setIconTitle(m[1]);
    579579    }],
    580     [/^\033\]0;([^\033\007]*)\007/, function (m) {
     580    [/^\x1b\]0;([^\x1b\x07]*)\x07/, function (m) {
    581581        this.emu.ev_setWindowIconTitle(m[1]);
    582582    }],
     
    588588    // graphics:       (1, )1, *1, +1  [g0, g1, g2, g3]
    589589    // graphics:       (2, )2, *2, +2  [g0, g1, g2, g3]
    590     [/^\033\$?([()*+-./])([ABCEHKQRYZ0124567=])/, function (m) {
     590    [/^\x1b\$?([()*+-./])([ABCEHKQRYZ0124567=])/, function (m) {
    591591        this.emu.ev_setCharset(m[1], m[2]);
    592592    }],
    593593
    594594    // temporary character set
    595     [/^\033N(a|[^a])/, function (m) {
     595    [/^\x1bN(a|[^a])/, function (m) {
    596596        this.emu.ev_g2char(m[1]);
    597597    }],
    598     [/^\033O(a|[^a])/, function (m) {
     598    [/^\x1bO(a|[^a])/, function (m) {
    599599        this.emu.ev_g3char(m[1]);
    600600    }],
    601601
    602602    // reports (skipped, we are not emulating an interactive terminal)
    603     [/^\033([0-9;?]*)n/, function (m) {
     603    [/^\x1b([0-9;?]*)n/, function (m) {
    604604        /*var me = this;
    605605        m[1].split(';').forEach(function (r) {
     
    607607            });*/
    608608    }],
    609     [/^\033(\[0?c|Z)/, function (m) {
     609    [/^\x1b(\[0?c|Z)/, function (m) {
    610610        //this.emu.ev_report('deviceAttributes');
    611611    }],
    612     [/^\033\[>c/, function (m) {
     612    [/^\x1b\[>c/, function (m) {
    613613        //this.emu.ev_report('versionString');
    614614    }],
    615615
    616616    // LEDs
    617     [/^\033\[([0-9;]*)q/, function (m) {
     617    [/^\x1b\[([0-9;]*)q/, function (m) {
    618618        var me = this;
    619619        (m[1].length ? m[1] : '0').split(';').forEach(function (l) {
     
    625625    // Print current screen, 1: print current line,
    626626    // 4: disable log, 5: enable log (echo to printer)
    627     [/^\033\[[145]?i/, function (m) {
     627    [/^\x1b\[[145]?i/, function (m) {
    628628    }],
    629629
    630630    //
    631     [/^\033\[([0-9;]*)y/, function (m) {
     631    [/^\x1b\[([0-9;]*)y/, function (m) {
    632632        this.emu.ev_hardware('selfTestRaw', m[1]);
    633633    }],
    634     [/^\033#8/, function (m) {
     634    [/^\x1b#8/, function (m) {
    635635        this.emu.ev_hardware('screenAlignment');
    636636    }],
    637637
    638638    // xterm: select default character set (ISO8859-1)
    639     [/^\033%@/, function (m) {
     639    [/^\x1b%@/, function (m) {
    640640        //enable utf8?
    641641        //this.cb('mode', 'utf8');
    642642    }],
    643643    // xterm: select default character set (ISO2022)
    644     [/^\033%G/, function (m) {
     644    [/^\x1b%G/, function (m) {
    645645        //enable utf8?
    646646        //this.cb('mode', 'utf8');
     
    648648
    649649    // screensaver control
    650     [/^\033\[9;([0-9]+)\]/, function (m) {
     650    [/^\x1b\[9;([0-9]+)\]/, function (m) {
    651651        //this.emu.ev_mode('borderColor', [ m[1], m[2] ]);
    652         // \033[9;X]  X in minutes (0 off)
     652        // \x1b[9;X]  X in minutes (0 off)
    653653    }],
    654654
    655655    // My extension to control the 'border color'
    656     [/^\033\[([0-9]+)(;[0-9]+)?\xb0/, function (m) {
     656    [/^\x1b\[([0-9]+)(;[0-9]+)?\xb0/, function (m) {
    657657        this.emu.ev_mode('borderColor', [ m[1], m[2] ? m[2].substr(1) : null ]);
    658658    }]
  • trunk/termtv/js/player.js

    r17408 r17948  
    220220
    221221        // Scan the data stream for the size sequence
    222         var re2 = new RegExp("\033\\[[8];([0-9]+);([0-9]+)t", "g");
     222        var re2 = new RegExp("\x1b\\[[8];([0-9]+);([0-9]+)t", "g");
    223223        while (!maxx && !maxy)
    224224        {
     
    234234
    235235        // Scan the data stream for goto sequence if no size sequence was found
    236         var re1 = new RegExp("\033\\[([0-9]+);([0-9]+)r", "g");
     236        var re1 = new RegExp("\x1b\\[([0-9]+);([0-9]+)r", "g");
    237237        while (1)
    238238        {
     
    335335            buffer += This.stream[i].data;
    336336
    337             var re2 = new RegExp("\033\\[[8];([0-9]+);([0-9]+)t", "g");
     337            var re2 = new RegExp("\x1b\\[[8];([0-9]+);([0-9]+)t", "g");
    338338            while (1)
    339339            {
     
    352352            if (!maxx && !maxy)
    353353            {
    354                 var re1 = new RegExp("\033\\[([0-9]+);([0-9]+)r", "g");
     354                var re1 = new RegExp("\x1b\\[([0-9]+);([0-9]+)r", "g");
    355355                while (1)
    356356                {
Note: See TracChangeset for help on using the changeset viewer.