code wiki / _hdl_build / nx_nishios_browser_input.nx

nx_nishios_browser_input.nx source

↩ module page · 397 lines · 23114 B

1// nx_nishios_browser_input.nx -- BROWSER-ON-ALL-OS arc, rung N2: the Nishi browser is USED on NishiOS. 2// 3// N1 (nx_nishios_browser) proved the browser RENDERS on NishiOS. This rung proves INPUT + NAVIGATION: 4// the OS delivers a click at the desktop point over a link in the rendered page; the browser maps it to 5// page coordinates, hit-tests it with the SAME br_hit_link the Linux/Windows browsers use, resolves the 6// href, loads the target page from the OS content store (disk), re-lays-out and re-renders -- a real 7// browse interaction (click a link -> the page changes), frame0/frame1 exported as BMPs. 8// 9// KAT: T1 booted off the persisted image; T2 LONG mode; T3 start page laid out; T4 the OS click HITS the 10// link box (br_hit_link==1); T5 the resolved href is exactly '/wiki/'; T6 the target page laid out; 11// T7 the target page rendered (h1 bar pixels in frame1); T8 frame0 and frame1 DIFFER across the window 12// region (navigation visibly changed the page); T9 both BMPs exported at the exact expected size. 13// NEG/liar-kill: T10 a click at a NON-link point hits nothing (no navigation -- input evidence is 14// box-sensitive, not a constant); T11 a 0-sector-load sibling image never reaches long mode -> no frame 15// is ever drawn. 16// 17// HONEST SEAM (same class as nx_nishios_events/kbd): the click SOURCE is scripted (a live PS/2 18// controller on the emu = the hardware rung); the click HANDLING (desktop->page mapping, br_hit_link, 19// href resolve, load, re-render) is the real browser input path. Navigation loads from DISK (the OS 20// content store); NishiOS-native network fetch = rung N3 (nx_nishios_net), named not claimed. 21// NEVER-BRICK (Rule 26): writes FILE artifacts only; models INT 13h *reads*; no /dev. 22// expect_exit: 0 license_tier: ORIGINAL 23import "nx_browser_render.nx" 24import "nx_fb.nx" 25const NB_MAGIC_200000: i64 = 200000 26const NB_MAGIC_32767: i64 = 32767 27const NB_MAGIC_65536: i64 = 65536 28 29func nb_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 30func nb_num(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 31func nb_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 32func nb_contains(hay: *u8, hn: i64, ndl: *u8, nn: i64) -> i64 { 33 if nn==0 { return 1 } 34 var i: i64 = 0 35 while i + nn <= hn { var j: i64 = 0; var ok: i64 = 1; while j < nn { if hay[i+j]!=ndl[j] { ok=0; j=nn } else { j=j+1 } } if ok==1 { return 1 } i=i+1 } 36 return 0 37} 38func nb_mode(cr0: i64, efer: i64) -> i64 { let pe: i64=cr0&1; let pg: i64=(cr0>>31)&1; let lme: i64=(efer>>8)&1; if pe==0 { return 0 } if pg==1 { if lme==1 { return 2 } } return 1 } 39 40// UNIFIED boot-disk emu (proven in nx_nishi_usb_longmode/_desktop and rung N1). 41func nb_emu_boot_disk(mem: *u8, disk: *u8, entry: i64, console: *u8, clen: *i64, st: *i64) -> i64 { 42 var ip: i64=entry 43 var ax: i64=0 44 var bx: i64=0 45 var cx: i64=0 46 var dx: i64=0 47 var si: i64=0 48 var zf: i64=0 49 var rax: i64=0 50 var cr0: i64=0 51 var efer: i64=0 52 var guard: i64=0 53 st[0]=0; st[1]=0 54 while guard < NB_MAGIC_200000 { 55 guard = guard + 1 56 let op: i64 = mem[ip] as i64 57 if op == 0xF4 { st[0]=cr0; st[1]=nb_mode(cr0,efer); return 0 } 58 var h: i64 = 0 59 if h==0 { if op==0x48 { 60 if mem[ip+1]==(0xC7 as u8) { 61 let modrm: i64 = mem[ip+2] as i64 62 let imm: i64 = (mem[ip+3] as i64) | ((mem[ip+4] as i64)<<8) | ((mem[ip+5] as i64)<<16) | ((mem[ip+6] as i64)<<24) 63 if modrm==0xC0 { rax = imm } 64 ip=ip+7; h=1 65 } 66 } } 67 if h==0 { if op==0x0F { 68 let b1: i64 = mem[ip+1] as i64 69 if b1==0x22 { let m: i64=mem[ip+2] as i64; if ((m>>3)&7)==0 { cr0=rax }; ip=ip+3; h=1 } 70 if h==0 { if b1==0x30 { efer=rax; ip=ip+2; h=1 } } 71 if h==0 { if b1==0x05 { st[0]=cr0; st[1]=nb_mode(cr0,efer); return rax & 0xff } } 72 if h==0 { return 0 - 1 } 73 } } 74 if h==0 { if op==0xBE { si = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 75 if h==0 { if op==0xB8 { ax = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 76 if h==0 { if op==0xBB { bx = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 77 if h==0 { if op==0xB9 { cx = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 78 if h==0 { if op==0xBA { dx = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); ip=ip+3; h=1 } } 79 if h==0 { if op==0xAC { let al: i64 = mem[si] as i64; ax = (ax & 0xFF00) | al; si=si+1; ip=ip+1; h=1 } } 80 if h==0 { if op==0x08 { let al2: i64 = ax & 0xFF; if al2==0 { zf=1 } else { zf=0 } ip=ip+2; h=1 } } 81 if h==0 { if op==0x74 { var r: i64 = mem[ip+1] as i64; if r>127 { r=r-256 } if zf==1 { ip=ip+2+r } else { ip=ip+2 } h=1 } } 82 if h==0 { if op==0xB4 { ax = (ax & 0xFF) | ((mem[ip+1] as i64)<<8); ip=ip+2; h=1 } } 83 if h==0 { if op==0xEB { var r2: i64 = mem[ip+1] as i64; if r2>127 { r2=r2-256 } ip=ip+2+r2; h=1 } } 84 if h==0 { if op==0xE9 { var r3: i64 = (mem[ip+1] as i64) | ((mem[ip+2] as i64)<<8); if r3>NB_MAGIC_32767 { r3=r3-NB_MAGIC_65536 } ip=ip+3+r3; h=1 } } 85 if h==0 { if op==0xCD { 86 let vec: i64 = mem[ip+1] as i64 87 let ah: i64 = (ax >> 8) & 0xFF 88 if vec==0x10 { if ah==0x0E { console[clen[0]]=(ax & 0xFF) as u8; clen[0]=clen[0]+1 } } 89 if vec==0x13 { if ah==0x02 { 90 let count: i64 = ax & 0xFF 91 let sector: i64 = cx & 0xFF 92 let lba: i64 = sector - 1 93 var s: i64 = 0 94 while s < count*512 { mem[bx + s] = disk[lba*512 + s]; s=s+1 } 95 ax = ax & 0xFF 96 } } 97 ip=ip+2; h=1 98 } } 99 if h==0 { return 0 - 1 } 100 } 101 return 0 - 2 102} 103 104const NB_IMG_SZ: i64 = 1024 105 106func nb_movrax(img: *u8, base: i64, o: i64, b0: i64, b1: i64, b2: i64, b3: i64) -> i64 { 107 img[base+o]=0x48 as u8; img[base+o+1]=0xC7 as u8; img[base+o+2]=0xC0 as u8 108 img[base+o+3]=(b0&0xff) as u8; img[base+o+4]=(b1&0xff) as u8; img[base+o+5]=(b2&0xff) as u8; img[base+o+6]=(b3&0xff) as u8 109 return o+7 110} 111func nb_build_image(img: *u8) -> i64 { 112 var z: i64=0 113 while z<NB_IMG_SZ { img[z]=0 as u8; z=z+1 } 114 img[0]=0xB8 as u8; img[1]=0x01 as u8; img[2]=0x02 as u8 115 img[3]=0xBB as u8; img[4]=0x00 as u8; img[5]=0x80 as u8 116 img[6]=0xB9 as u8; img[7]=0x02 as u8; img[8]=0x00 as u8 117 img[9]=0xBA as u8; img[10]=0x80 as u8; img[11]=0x00 as u8 118 img[12]=0xCD as u8; img[13]=0x13 as u8 119 let rel16: i64 = 0x8000 - (0x7C00 + 14 + 3) 120 img[14]=0xE9 as u8; img[15]=(rel16 & 0xFF) as u8; img[16]=((rel16>>8) & 0xFF) as u8 121 img[510]=0x55 as u8; img[511]=0xAA as u8 122 var r: i64 = 0 123 img[512+r]=0xBE as u8; let si_r: i64 = r+1; r=r+3 124 let loop_r: i64 = r 125 img[512+r]=0xAC as u8; r=r+1 126 img[512+r]=0x08 as u8; img[512+r+1]=0xC0 as u8; r=r+2 127 img[512+r]=0x74 as u8; let jz_r: i64 = r+1; r=r+2 128 img[512+r]=0xB4 as u8; img[512+r+1]=0x0E as u8; r=r+2 129 img[512+r]=0xCD as u8; img[512+r+1]=0x10 as u8; r=r+2 130 img[512+r]=0xEB as u8; img[512+r+1]=((loop_r-(r+2)) & 0xFF) as u8; r=r+2 131 let after_r: i64 = r 132 r = nb_movrax(img, 512, r, 1, 0, 0, 0) 133 img[512+r]=0x0F as u8; img[512+r+1]=0x22 as u8; img[512+r+2]=0xC0 as u8; r=r+3 134 r = nb_movrax(img, 512, r, 0x00, 0x01, 0, 0) 135 img[512+r]=0x0F as u8; img[512+r+1]=0x30 as u8; r=r+2 136 r = nb_movrax(img, 512, r, 0x01, 0x00, 0x00, 0x80) 137 img[512+r]=0x0F as u8; img[512+r+1]=0x22 as u8; img[512+r+2]=0xC0 as u8; r=r+3 138 img[512+r]=0xF4 as u8; r=r+1 139 let msg_r: i64 = r 140 let msg: *u8 = "NishiOS\x0D\x0A\x00" 141 var mi: i64=0 142 while msg[mi]!=(0 as u8) { img[512+r]=msg[mi]; r=r+1; mi=mi+1 } 143 img[512+r]=0 as u8; r=r+1 144 img[512+jz_r] = ((after_r - (jz_r+1)) & 0xFF) as u8 145 let si_abs: i64 = 0x8000 + msg_r 146 img[512+si_r] = (si_abs & 0xFF) as u8 147 img[512+si_r+1] = ((si_abs>>8) & 0xFF) as u8 148 return 0 149} 150func nb_boot_image(img: *u8, console: *u8, clen: *i64, st: *i64, loaded: *i64) -> i64 { 151 let mem: *u8 = sys_mmap(NB_MAGIC_65536) 152 var k: i64=0 153 while k<NB_MAGIC_65536 { mem[k]=0 as u8; k=k+1 } 154 var j: i64=0 155 while j<512 { mem[0x7C00+j]=img[j]; j=j+1 } 156 loaded[0] = mem[0x8000] as i64 157 clen[0]=0 158 let rc: i64 = nb_emu_boot_disk(mem, img, 0x7C00, console, clen, st) 159 loaded[1] = mem[0x8000] as i64 160 return rc 161} 162 163func nb_str(fb: *u8, W: i64, H: i64, x: i64, y: i64, s: *u8, r: i64, g: i64, b: i64) -> i64 { 164 let table: *u8 = font8x8_table() 165 var i: i64=0 166 while s[i]!=(0 as u8) { 167 let cc: i64 = s[i] as i64 168 if cc>=0x20 { if cc<=0x7E { 169 let gi: i64=(cc-0x20)*8 170 var rr: i64=0 171 while rr<8 { let bits: i64=table[gi+rr] as i64; var co: i64=0; while co<8 { if ((bits>>co)&1)==1 { fb_setpx(fb,W,H, x+i*8+co, y+rr, r,g,b) } co=co+1 } rr=rr+1 } 172 } } 173 i=i+1 174 } 175 return 0 176} 177func nb_write_file(path: *u8, data: *u8, n: i64) -> i64 { 178 let fd: i64 = sys_openat_wr(path, 0x1a4) 179 if fd<=0 { return 0 - 1 } 180 sys_write(fd, data, n) 181 sys_close(fd) 182 return n 183} 184 185const NB_W: i64 = 640 186const NB_H: i64 = 480 187const NB_BW: i64 = 620 188const NB_BH: i64 = 426 189const NB_OX: i64 = 10 190const NB_OY: i64 = 38 191 192// draw the NishiOS desktop with the browser window showing `page`, cursor at desktop (cx,cy) 193func nb_draw_desktop(desk: *u8, page: *Page, url: *u8, ulen: i64, cx: i64, cy: i64) -> i64 { 194 let font: *u8 = sys_mmap(64) 195 let idx: *u8 = sys_mmap(8) 196 fb_nishi_font(font, idx) 197 var wy: i64=0 198 while wy<NB_H { let wr: i64=10-(8*wy)/NB_H; let wg: i64=30+(40*wy)/NB_H; let wb: i64=50+(30*wy)/NB_H; fb_rect(desk,NB_W,NB_H, 0,wy, NB_W,1, wr,wg,wb); wy=wy+1 } 199 fb_rect(desk,NB_W,NB_H, 0,0, NB_W,16, 28,28,110) 200 fb_text(desk,NB_W,NB_H, font, idx, 7, 6,4, 1, 255,255,255) 201 fb_window(desk,NB_W,NB_H, font,idx, 8,22, 624,444, 50,80,180, 210,210,225) 202 nb_str(desk,NB_W,NB_H, 8+3+66, 22+3, "- NISHI BROWSER\x00" as *u8, 240,240,250) 203 let bfb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer 204 let bpx: *u8 = sys_mmap(NB_BW*NB_BH*4 + 64) 205 nx_framebuffer_init(bfb, bpx, NB_BW, NB_BH) 206 br_draw_fb(bfb, page, NB_BW/2, url, ulen, 2) 207 var by: i64 = 0 208 while by < NB_BH { 209 var bx: i64 = 0 210 while bx < NB_BW { 211 let so: i64 = (by*NB_BW + bx)*4 212 let dof: i64 = ((NB_OY+by)*NB_W + (NB_OX+bx))*3 213 desk[dof] = bpx[so] 214 desk[dof+1] = bpx[so+1] 215 desk[dof+2] = bpx[so+2] 216 bx = bx + 1 217 } 218 by = by + 1 219 } 220 fb_rect(desk,NB_W,NB_H, 0,466, NB_W,14, 20,20,40) 221 fb_rect(desk,NB_W,NB_H, 4,469, 36,8, 80,200,80) 222 nb_str(desk,NB_W,NB_H, 46,469, "browser\x00" as *u8, 200,210,230) 223 fb_cursor(desk,NB_W,NB_H, cx, cy) 224 return 0 225} 226 227// find the first link box whose href equals want; out ox,oy = a page-coord point inside its rect 228func nb_find_link(page: *Page, want: *u8, wlen: i64, ox: *i64, oy: *i64) -> i64 { 229 let tree: *LayoutTree = page.tree 230 var i: i64=0 231 while i < tree.count { 232 if page.bhref_off[i] >= 0 { if page.bhref_len[i]==wlen { 233 var ok: i64=1 234 var k: i64=0 235 while k<wlen { if (page.buf[page.bhref_off[i]+k]&0xff)!=(want[k]&0xff) { ok=0; k=wlen } else { k=k+1 } } 236 if ok==1 { 237 let b: *LayoutBox = ((tree.boxes as i64)+i*NX_LAYOUT_BOX_BYTES) as *LayoutBox 238 ox[0]=b.x+2 239 oy[0]=b.y+2 240 return 1 241 } 242 } } 243 i=i+1 244 } 245 return 0 246} 247 248func main() -> i64 { 249 nb_puts("BROWSER-ON-ALL-OS N2: click a link INSIDE the Nishi browser on NishiOS -> it navigates\n" as *u8) 250 251 // ---- 1. persist + boot the NishiOS image (same proven chain as N1) 252 let img: *u8 = sys_mmap(NB_IMG_SZ + 16) 253 nb_build_image(img) 254 if nb_write_file("knowledge/status/nishios_browser.img\x00" as *u8, img, NB_IMG_SZ) <= 0 { nb_puts("N2 RED: cannot write image\n" as *u8); sys_exit(1); return 1 } 255 let ilp: *i64 = sys_mmap(16) as *i64 256 let rd: *u8 = sys_read_file("knowledge/status/nishios_browser.img\x00" as *u8, ilp) 257 let con: *u8 = sys_mmap(256) 258 let clen: *i64 = sys_mmap(8) as *i64 259 let st: *i64 = sys_mmap(64) as *i64 260 let ld: *i64 = sys_mmap(64) as *i64 261 nb_boot_image(rd, con, clen, st, ld) 262 nb_puts(" boot: 0x8000 " as *u8); nb_num(ld[0]); nb_puts("->" as *u8); nb_num(ld[1]); nb_puts(" mode=" as *u8); nb_num(st[1]); nb_puts("\n" as *u8) 263 264 // ---- 2. the OS content store: persist the start page and the /wiki/ target page 265 let ahtml: *u8 = "<html><head><title>Nishi Browser on NishiOS</title></head><body><h1>Nishi</h1><p><b>Links:</b> <a href='https://nishifamily.com/'>nishifamily.com</a> and the <a href='/wiki/'>NishiOS wiki</a>.</p><p>The sovereign browser on the sovereign NishiOS: own HTML tokenizer, own CSS cascade, own layout, own paint &amp; fonts.</p><h2>The stack under this page</h2><ul><li>boot: MBR loader, INT 13h, real to protected to LONG mode</li><li>render: the same br_layout core as Linux + Windows</li><li>paint: nx_fb, the NishiOS framebuffer driver</li></ul><h2>Status</h2><p>Rendered by the Nishi browser core, composited into the NishiOS desktop.</p></body></html>\x00" 266 nb_write_file("knowledge/status/nishios_browser_page.html\x00" as *u8, ahtml, nb_slen(ahtml)) 267 let whtml: *u8 = "<html><head><title>NishiOS Wiki</title></head><body><h1>NishiOS Wiki</h1><p>You navigated here by clicking a link inside the Nishi browser running on NishiOS.</p><h2>The input path</h2><ul><li>OS event: a click on the link box in the desktop</li><li>browser: br_hit_link mapped the point to the href</li><li>navigate: /wiki/ loaded from the OS content store</li></ul><p>Back to the <a href='/'>start page</a>.</p></body></html>\x00" 268 nb_write_file("knowledge/status/nishios_browser_wiki.html\x00" as *u8, whtml, nb_slen(whtml)) 269 270 // ---- 3. browser: lay out the start page (only because the kernel reached long mode) 271 let plp: *i64 = sys_mmap(16) as *i64 272 let praw: *u8 = sys_read_file("knowledge/status/nishios_browser_page.html\x00" as *u8, plp) 273 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 274 page.raw = praw 275 page.raw_len = plp[0] 276 var a_ok: i64 = 0 277 if st[1]==2 { br_layout(page, NB_BW/2); a_ok = page.ok; page.vec_headings = 2 } // 16px + modern vector headings 278 nb_puts(" start page: ok=" as *u8); nb_num(a_ok); nb_puts(" boxes=" as *u8); if a_ok==1 { nb_num(page.tree.count) } else { nb_num(0) } nb_puts("\n" as *u8) 279 280 // ---- 4. the OS delivers a click on the '/wiki/' link; the browser hit-tests + resolves it 281 let want: *u8 = "/wiki/\x00" as *u8 282 let lx: *i64 = sys_mmap(16) as *i64 283 let ly: *i64 = sys_mmap(16) as *i64 284 var found: i64 = 0 285 if a_ok==1 { found = nb_find_link(page, want, 6, lx, ly) } 286 // desktop coords of the click = window origin + 2x-scaled (page point + chrome offset) -- the draw 287 // paints page content at ((b.x)*2, (b.y+NX_CHROME_H)*2) inside the window 288 var dcx: i64 = 0 289 var dcy: i64 = 0 290 if found==1 { dcx = NB_OX + lx[0]*2; dcy = NB_OY + (NX_CHROME_H + ly[0])*2 } 291 nb_puts(" click target: found=" as *u8); nb_num(found); nb_puts(" page(" as *u8); nb_num(lx[0]); nb_puts("," as *u8); nb_num(ly[0]); nb_puts(") desktop(" as *u8); nb_num(dcx); nb_puts("," as *u8); nb_num(dcy); nb_puts(")\n" as *u8) 292 // the browser input handler: desktop -> page coords (inverse of the 2x draw) -> br_hit_link 293 let ho: *i64 = sys_mmap(16) as *i64 294 let hl: *i64 = sys_mmap(16) as *i64 295 var hit: i64 = 0 296 if found==1 { hit = br_hit_link(page, (dcx - NB_OX)/2, (dcy - NB_OY)/2 - NX_CHROME_H, ho, hl) } 297 var href_ok: i64 = 0 298 if hit==1 { if hl[0]==6 { 299 var hk: i64=0 300 var hok: i64=1 301 while hk<6 { if (page.buf[ho[0]+hk]&0xff)!=(want[hk]&0xff) { hok=0; hk=6 } else { hk=hk+1 } } 302 href_ok = hok 303 } } 304 nb_puts(" hit=" as *u8); nb_num(hit); nb_puts(" href_len=" as *u8); nb_num(hl[0]); nb_puts(" href_ok=" as *u8); nb_num(href_ok); nb_puts("\n" as *u8) 305 306 // ---- 5. navigate: resolve '/wiki/' in the OS content store, re-layout, re-render both frames 307 let wlp: *i64 = sys_mmap(16) as *i64 308 let wraw: *u8 = sys_read_file("knowledge/status/nishios_browser_wiki.html\x00" as *u8, wlp) 309 let page2: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 310 page2.raw = wraw 311 page2.raw_len = wlp[0] 312 var b_ok: i64 = 0 313 if href_ok==1 { br_layout(page2, NB_BW/2); b_ok = page2.ok; page2.vec_headings = 2 } 314 nb_puts(" wiki page: ok=" as *u8); nb_num(b_ok); nb_puts(" boxes=" as *u8); if b_ok==1 { nb_num(page2.tree.count) } else { nb_num(0) } nb_puts("\n" as *u8) 315 316 let desk0: *u8 = sys_mmap(NB_W*NB_H*3 + 16) 317 let desk1: *u8 = sys_mmap(NB_W*NB_H*3 + 16) 318 var bmp0: i64 = 0 319 var bmp1: i64 = 0 320 if a_ok==1 { if b_ok==1 { 321 nb_draw_desktop(desk0, page, "nishios://start\x00" as *u8, 15, dcx, dcy) 322 nb_draw_desktop(desk1, page2, "nishios://wiki\x00" as *u8, 14, dcx, dcy) 323 bmp0 = fb_bmp_save(desk0, NB_W, NB_H, "knowledge/status/nishios_browser_click0.bmp\x00" as *u8) 324 bmp1 = fb_bmp_save(desk1, NB_W, NB_H, "knowledge/status/nishios_browser_click1.bmp\x00" as *u8) 325 let html: *u8 = "<!doctype html><html><body style=\x27margin:0;background:#0a0a12;color:#8af;font-family:monospace;text-align:center\x27><h3 style=\x27margin:10px\x27>NishiOS browser input: click the wiki link (frame 0, cursor on the link) -&gt; the browser navigates (frame 1)</h3><img src=\x27nishios_browser_click0.bmp\x27 style=\x27image-rendering:pixelated;width:640px;border:1px solid #333;margin:4px\x27><img src=\x27nishios_browser_click1.bmp\x27 style=\x27image-rendering:pixelated;width:640px;border:1px solid #333;margin:4px\x27><div style=\x27margin:8px\x27>the same br_hit_link input path as the Linux/Windows Nishi browser, running over the NishiOS desktop</div></body></html>\x00" 326 nb_write_file("knowledge/status/nishios_browser_input.html\x00" as *u8, html, nb_slen(html)) 327 nb_puts(" frames -> knowledge/status/nishios_browser_click0.bmp + click1.bmp + nishios_browser_input.html\n" as *u8) 328 } } 329 330 // frame diff over the window region 331 var ndiff: i64 = 0 332 var dy2: i64 = 0 333 while dy2 < NB_BH { 334 var dx2: i64 = 0 335 while dx2 < NB_BW { 336 let o2: i64 = ((NB_OY+dy2)*NB_W + (NB_OX+dx2))*3 337 if desk0[o2]!=desk1[o2] { ndiff=ndiff+1 } 338 dx2 = dx2 + 1 339 } 340 dy2 = dy2 + 1 341 } 342 // frame1 h1-bar pixels (the wiki page rendered for real) 343 var cnt_h1: i64 = 0 344 var cy2: i64 = 0 345 while cy2 < NB_BH { 346 var cx2: i64 = 0 347 while cx2 < NB_BW { 348 let o3: i64 = ((NB_OY+cy2)*NB_W + (NB_OX+cx2))*3 349 if (desk1[o3] as i64)==20 { if (desk1[o3+1] as i64)==20 { if (desk1[o3+2] as i64)==43 { cnt_h1=cnt_h1+1 } } } // #14142b heading ink (modern, no bar) 350 cx2 = cx2 + 1 351 } 352 cy2 = cy2 + 1 353 } 354 nb_puts(" frame_diff=" as *u8); nb_num(ndiff); nb_puts(" frame1_h1bar=" as *u8); nb_num(cnt_h1); nb_puts("\n" as *u8) 355 356 // ---- 6. NEG: a click on a NON-link point hits nothing (no navigation) 357 let no: *i64 = sys_mmap(16) as *i64 358 let nl: *i64 = sys_mmap(16) as *i64 359 var neg_hit: i64 = 0 - 1 360 if a_ok==1 { neg_hit = br_hit_link(page, 2, 6, no, nl) } // top-left margin: no link box there 361 nb_puts(" NEG non-link click: hit=" as *u8); nb_num(neg_hit); nb_puts("\n" as *u8) 362 363 // ---- 7. NEG: 0-sector boot never draws a frame 364 let bad: *u8 = sys_mmap(NB_IMG_SZ + 16) 365 var c: i64=0 366 while c<NB_IMG_SZ { bad[c]=rd[c]; c=c+1 } 367 bad[1]=0x00 as u8 368 let con2: *u8 = sys_mmap(256) 369 let clen2: *i64 = sys_mmap(8) as *i64 370 let st2: *i64 = sys_mmap(64) as *i64 371 let ld2: *i64 = sys_mmap(64) as *i64 372 nb_boot_image(bad, con2, clen2, st2, ld2) 373 let desk2: *u8 = sys_mmap(NB_W*NB_H*3 + 16) 374 var neg_drawn: i64 = 0 375 if st2[1]==2 { neg_drawn = 1 } 376 let negpx: i64 = desk2[((NB_OY+50)*NB_W + (NB_OX+50))*3] as i64 377 378 // ---- KATs 379 let banner: *u8 = "NishiOS" as *u8 380 var pass: i64=0 381 var ttl: i64=0 382 ttl=ttl+1; nb_puts(" T1 booted off the persisted image (0x8000: 0->0xBE): " as *u8); if ld[0]==0 { if ld[1]==0xBE { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 383 ttl=ttl+1; nb_puts(" T2 disk-loaded kernel reached LONG mode + banner: " as *u8); if st[1]==2 { if nb_contains(con, clen[0], banner, 7)==1 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 384 ttl=ttl+1; nb_puts(" T3 start page laid out (ok, boxes>=15): " as *u8); if a_ok==1 { if page.tree.count>=15 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 385 ttl=ttl+1; nb_puts(" T4 the OS click HITS the link box (br_hit_link==1): " as *u8); if hit==1 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 386 ttl=ttl+1; nb_puts(" T5 resolved href == '/wiki/': " as *u8); if href_ok==1 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 387 ttl=ttl+1; nb_puts(" T6 target page laid out (ok, boxes>=10): " as *u8); if b_ok==1 { if page2.tree.count>=10 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 388 ttl=ttl+1; nb_puts(" T7 target page rendered (frame1 heading ink >100 px): " as *u8); if cnt_h1>100 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 389 ttl=ttl+1; nb_puts(" T8 navigation visibly changed the page (frame diff >1000 px): " as *u8); if ndiff>1000 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 390 ttl=ttl+1; nb_puts(" T9 both frames exported at the exact expected size: " as *u8); if bmp0==(54 + NB_W*NB_H*3) { if bmp1==(54 + NB_W*NB_H*3) { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 391 ttl=ttl+1; nb_puts(" T10 NEG: a non-link click hits nothing (input is box-sensitive): " as *u8); if neg_hit==0 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } 392 ttl=ttl+1; nb_puts(" T11 NEG: 0-sector load never reaches long mode, no frame drawn: " as *u8); if st2[1]!=2 { if neg_drawn==0 { if negpx==0 { pass=pass+1; nb_puts("PASS\n" as *u8) } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } } else { nb_puts("FAIL\n" as *u8) } 393 394 nb_puts("NISHIOS-BROWSER-INPUT-GATE passed " as *u8); nb_num(pass); nb_puts("/" as *u8); nb_num(ttl) 395 if pass==ttl { nb_puts(" verdict=GREEN (click -> navigate on NishiOS; open knowledge/status/nishios_browser_input.html)\n" as *u8); sys_exit(0); return 0 } 396 nb_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1 397}