Full Code of klange/toaruos for AI

master e67515e5d59a cached
787 files
3.8 MB
1.0M tokens
5110 symbols
1 requests
Download .txt
Showing preview only (4,056K chars total). Download the full file or copy to clipboard to get everything.
Repository: klange/toaruos
Branch: master
Commit: e67515e5d59a
Files: 787
Total size: 3.8 MB

Directory structure:
gitextract_orn7wwbb/

├── .github/
│   ├── FUNDING.yml
│   ├── SECURITY.md
│   └── workflows/
│       ├── aarch64.yml
│       └── x86_64.yml
├── .gitignore
├── .gitmodules
├── .mailmap
├── AUTHORS
├── LICENSE
├── Makefile
├── README.md
├── apps/
│   ├── about.c
│   ├── basename.c
│   ├── beep.c
│   ├── bim.c
│   ├── bim.h
│   ├── block-dev-stats.c
│   ├── cal.c
│   ├── calculator.c
│   ├── cat-img.c
│   ├── cat.c
│   ├── chmod.c
│   ├── chown.c
│   ├── clear.c
│   ├── cmp.c
│   ├── color-picker.c
│   ├── compositor.c
│   ├── cp.c
│   ├── cpu-name.krk
│   ├── cpuwidget.c
│   ├── crc32.c
│   ├── cursor-off.c
│   ├── date.c
│   ├── dbg.c
│   ├── demo.c
│   ├── demo.krk
│   ├── dhclient.c
│   ├── dirname.c
│   ├── drawlines.c
│   ├── du.c
│   ├── echo.c
│   ├── env.c
│   ├── esh.c
│   ├── false.c
│   ├── fetch.c
│   ├── file-browser.c
│   ├── find-timezone.c
│   ├── font-preview.c
│   ├── font-tool.c
│   ├── free.c
│   ├── getty.c
│   ├── glogin-provider.c
│   ├── glogin.c
│   ├── grep.c
│   ├── groups.c
│   ├── gsudo.c
│   ├── gunzip.c
│   ├── head.c
│   ├── hello.c
│   ├── help-browser.c
│   ├── hexify.c
│   ├── highlight-source.krk
│   ├── hostname.c
│   ├── ifconfig.c
│   ├── imgviewer.c
│   ├── init.c
│   ├── insmod.c
│   ├── irc.c
│   ├── json-test.c
│   ├── julia.c
│   ├── kbd-test.c
│   ├── kcmdline.c
│   ├── kill.c
│   ├── killall.c
│   ├── krk_test_noise.krk
│   ├── krk_yutani_test.krk
│   ├── live-session.c
│   ├── ln.c
│   ├── login-loop.c
│   ├── login.c
│   ├── logname.c
│   ├── ls.c
│   ├── lspci.c
│   ├── maybe-pdfviewer.krk
│   ├── migrate.c
│   ├── mines.krk
│   ├── misaka-test.c
│   ├── mixerctl.c
│   ├── mkdir.c
│   ├── mktemp.c
│   ├── more.c
│   ├── mount.c
│   ├── msk.c
│   ├── mv.c
│   ├── netty.c
│   ├── nproc.c
│   ├── nslookup.c
│   ├── nyancat/
│   │   ├── animation.h
│   │   └── telnet.h
│   ├── nyancat.c
│   ├── package-manager.c
│   ├── panel.c
│   ├── path_demo.krk
│   ├── piano.c
│   ├── pidof.c
│   ├── ping.c
│   ├── plasma.c
│   ├── play.c
│   ├── polygons.c
│   ├── pong.c
│   ├── prompt_and_delete.krk
│   ├── ps.c
│   ├── pstree.c
│   ├── pwd.c
│   ├── qemu-display-hack.c
│   ├── qemu-fwcfg.c
│   ├── readelf.c
│   ├── readlink.c
│   ├── reboot.c
│   ├── reload_desktop.sh
│   ├── reset.c
│   ├── rm.c
│   ├── rmdir.c
│   ├── serial-console.c
│   ├── session.c
│   ├── set-resolution.c
│   ├── set-wallpaper.sh
│   ├── show-toasts.krk
│   ├── show-tutorial.sh
│   ├── showdialog.c
│   ├── sleep.c
│   ├── snow.c
│   ├── sort.c
│   ├── splash-log.c
│   ├── stat.c
│   ├── strace.c
│   ├── strings.c
│   ├── stty.c
│   ├── sudo.c
│   ├── sync.c
│   ├── sysfunc.c
│   ├── sysinfo.c
│   ├── t_mbstowcs.c
│   ├── tar.c
│   ├── tee.c
│   ├── terminal-font.h
│   ├── terminal-palette.h
│   ├── terminal-vga.c
│   ├── terminal.c
│   ├── test-badwrite.c
│   ├── test-conf.c
│   ├── test-fpclassify.c
│   ├── test-ftruncate.c
│   ├── test-localtime.c
│   ├── test-lock.c
│   ├── test-loop.c
│   ├── test-printf.c
│   ├── test-ptrace-syscall.c
│   ├── test-sigsegv.c
│   ├── test-sigsuspend.c
│   ├── test-sigwait.c
│   ├── test-syscall-sysret.c
│   ├── test-tls.c
│   ├── test-tty-read.c
│   ├── test-udp-recv.krk
│   ├── toaru_logo.h
│   ├── toast.krk
│   ├── toastd.c
│   ├── toggle-abs-mouse.c
│   ├── top.c
│   ├── touch.c
│   ├── true.c
│   ├── tty.c
│   ├── ttysize.c
│   ├── tutorial.c
│   ├── uname.c
│   ├── ununicode.h
│   ├── upload.krk
│   ├── uptime.c
│   ├── vga-palette.h
│   ├── wallpaper-picker.c
│   ├── wc.c
│   ├── weather-configurator.c
│   ├── weather-tool.c
│   ├── which.c
│   ├── whoami.c
│   ├── yes.c
│   ├── yutani-clipboard.c
│   ├── yutani-kbd.c
│   ├── yutani-query.c
│   ├── yutani-test.c
│   ├── yutani-tty-pipe.c
│   └── zcat.c
├── base/
│   ├── etc/
│   │   ├── demo.conf
│   │   ├── group
│   │   ├── hostname
│   │   ├── master.passwd
│   │   ├── motd
│   │   ├── msk.conf
│   │   ├── panel.menu
│   │   ├── passwd
│   │   ├── startup.d/
│   │   │   ├── 00_startuplog.sh
│   │   │   ├── 01_migrate.sh
│   │   │   ├── 02_hostname.sh
│   │   │   ├── 03_tmpfs.sh
│   │   │   ├── 04_modprobe.sh
│   │   │   ├── 05_mountcd.sh
│   │   │   ├── 40_dhcp.sh
│   │   │   ├── 50_msk.sh
│   │   │   └── 99_runstart.sh
│   │   ├── sudoers
│   │   └── weather.json
│   ├── home/
│   │   ├── guest/
│   │   │   └── hello
│   │   ├── local/
│   │   │   ├── .bim3rc
│   │   │   ├── .eshrc
│   │   │   ├── .wallpaper.conf
│   │   │   ├── .yutanirc
│   │   │   ├── Desktop/
│   │   │   │   ├── 0_file_browser.launcher
│   │   │   │   ├── 1_terminal.launcher
│   │   │   │   ├── 2_packages.launcher
│   │   │   │   └── 3_read_me.launcher
│   │   │   ├── README.md
│   │   │   └── text_layout.krk
│   │   └── root/
│   │       ├── .bimrc
│   │       └── hello
│   ├── lib/
│   │   └── .dummy
│   └── usr/
│       ├── include/
│       │   ├── _cheader.h
│       │   ├── alloca.h
│       │   ├── arpa/
│       │   │   └── inet.h
│       │   ├── assert.h
│       │   ├── bits/
│       │   │   ├── dirent.h
│       │   │   └── timespec.h
│       │   ├── ctype.h
│       │   ├── dirent.h
│       │   ├── dlfcn.h
│       │   ├── errno.h
│       │   ├── fcntl.h
│       │   ├── getopt.h
│       │   ├── iconv.h
│       │   ├── inttypes.h
│       │   ├── kernel/
│       │   │   ├── arch/
│       │   │   │   ├── aarch64/
│       │   │   │   │   ├── dtb.h
│       │   │   │   │   ├── gic.h
│       │   │   │   │   ├── pml.h
│       │   │   │   │   ├── regs.h
│       │   │   │   │   └── rpi.h
│       │   │   │   └── x86_64/
│       │   │   │       ├── acpi.h
│       │   │   │       ├── cmos.h
│       │   │   │       ├── irq.h
│       │   │   │       ├── pml.h
│       │   │   │       ├── ports.h
│       │   │   │       └── regs.h
│       │   │   ├── args.h
│       │   │   ├── assert.h
│       │   │   ├── elf.h
│       │   │   ├── generic.h
│       │   │   ├── gzip.h
│       │   │   ├── hashmap.h
│       │   │   ├── ksym.h
│       │   │   ├── list.h
│       │   │   ├── misc.h
│       │   │   ├── mmu.h
│       │   │   ├── mod/
│       │   │   │   ├── rtl.h
│       │   │   │   ├── shell.h
│       │   │   │   ├── snd.h
│       │   │   │   └── sound.h
│       │   │   ├── module.h
│       │   │   ├── mouse.h
│       │   │   ├── multiboot.h
│       │   │   ├── mutex.h
│       │   │   ├── net/
│       │   │   │   ├── e1000.h
│       │   │   │   ├── eth.h
│       │   │   │   ├── ipv4.h
│       │   │   │   └── netif.h
│       │   │   ├── pci.h
│       │   │   ├── pipe.h
│       │   │   ├── printf.h
│       │   │   ├── process.h
│       │   │   ├── procfs.h
│       │   │   ├── ptrace.h
│       │   │   ├── pty.h
│       │   │   ├── ramdisk.h
│       │   │   ├── ringbuffer.h
│       │   │   ├── shm.h
│       │   │   ├── signal.h
│       │   │   ├── spinlock.h
│       │   │   ├── string.h
│       │   │   ├── symboltable.h
│       │   │   ├── syscall.h
│       │   │   ├── time.h
│       │   │   ├── tmpfs.h
│       │   │   ├── tokenize.h
│       │   │   ├── tree.h
│       │   │   ├── types.h
│       │   │   ├── version.h
│       │   │   ├── vfs.h
│       │   │   └── video.h
│       │   ├── libgen.h
│       │   ├── libintl.h
│       │   ├── limits.h
│       │   ├── locale.h
│       │   ├── math.h
│       │   ├── memory.h
│       │   ├── net/
│       │   │   └── if.h
│       │   ├── netdb.h
│       │   ├── netinet/
│       │   │   └── in.h
│       │   ├── poll.h
│       │   ├── pthread.h
│       │   ├── pty.h
│       │   ├── pwd.h
│       │   ├── sched.h
│       │   ├── setjmp.h
│       │   ├── signal.h
│       │   ├── stdint.h
│       │   ├── stdio.h
│       │   ├── stdlib.h
│       │   ├── string.h
│       │   ├── strings.h
│       │   ├── sys/
│       │   │   ├── fswait.h
│       │   │   ├── ioctl.h
│       │   │   ├── mman.h
│       │   │   ├── mount.h
│       │   │   ├── param.h
│       │   │   ├── ptrace.h
│       │   │   ├── shm.h
│       │   │   ├── signal.h
│       │   │   ├── signal_defs.h
│       │   │   ├── socket.h
│       │   │   ├── stat.h
│       │   │   ├── sysfunc.h
│       │   │   ├── termios.h
│       │   │   ├── time.h
│       │   │   ├── times.h
│       │   │   ├── types.h
│       │   │   ├── uregs.h
│       │   │   ├── utsname.h
│       │   │   └── wait.h
│       │   ├── syscall.h
│       │   ├── syscall_nums.h
│       │   ├── termio.h
│       │   ├── termios.h
│       │   ├── time.h
│       │   ├── toaru/
│       │   │   ├── auth.h
│       │   │   ├── button.h
│       │   │   ├── confreader.h
│       │   │   ├── decodeutf8.h
│       │   │   ├── decorations.h
│       │   │   ├── drawstring.h
│       │   │   ├── graphics.h
│       │   │   ├── hashmap.h
│       │   │   ├── icon_cache.h
│       │   │   ├── inflate.h
│       │   │   ├── jpeg.h
│       │   │   ├── json.h
│       │   │   ├── kbd.h
│       │   │   ├── list.h
│       │   │   ├── markup.h
│       │   │   ├── markup_text.h
│       │   │   ├── menu.h
│       │   │   ├── mouse.h
│       │   │   ├── panel.h
│       │   │   ├── pex.h
│       │   │   ├── png.h
│       │   │   ├── rline.h
│       │   │   ├── spinlock.h
│       │   │   ├── termemu.h
│       │   │   ├── text.h
│       │   │   ├── trace.h
│       │   │   ├── tree.h
│       │   │   ├── yutani-internal.h
│       │   │   ├── yutani-server.h
│       │   │   └── yutani.h
│       │   ├── unistd.h
│       │   ├── utime.h
│       │   ├── va_list.h
│       │   ├── wait.h
│       │   └── wchar.h
│       └── share/
│           ├── bim/
│           │   ├── site/
│           │   │   └── __init__.krk
│           │   ├── syntax/
│           │   │   ├── __init__.krk
│           │   │   ├── bash.krk
│           │   │   ├── biminfo.krk
│           │   │   ├── c.krk
│           │   │   ├── conf.krk
│           │   │   ├── css.krk
│           │   │   ├── ctags.krk
│           │   │   ├── diff.krk
│           │   │   ├── dirent.krk
│           │   │   ├── dlang.krk
│           │   │   ├── docker.krk
│           │   │   ├── doxygen.krk
│           │   │   ├── esh.krk
│           │   │   ├── gas.krk
│           │   │   ├── git.krk
│           │   │   ├── graphql.krk
│           │   │   ├── groovy.krk
│           │   │   ├── hosts.krk
│           │   │   ├── issue.krk
│           │   │   ├── java.krk
│           │   │   ├── javascript.krk
│           │   │   ├── json.krk
│           │   │   ├── krk.krk
│           │   │   ├── latex.krk
│           │   │   ├── ld.krk
│           │   │   ├── lisp.krk
│           │   │   ├── lua.krk
│           │   │   ├── make.krk
│           │   │   ├── man.krk
│           │   │   ├── markdown.krk
│           │   │   ├── protobuf.krk
│           │   │   ├── py.krk
│           │   │   ├── rust.krk
│           │   │   └── xml.krk
│           │   └── themes/
│           │       ├── __init__.krk
│           │       ├── ansi.krk
│           │       ├── citylights.krk
│           │       ├── light.krk
│           │       ├── solarized.krk
│           │       ├── strawberry.krk
│           │       ├── sunsmoke.krk
│           │       ├── tiff.krk
│           │       └── wombat.krk
│           └── help/
│               ├── 0_index.trt
│               ├── calculator.trt
│               ├── file-browser.trt
│               ├── help-browser.trt
│               ├── package-manager.trt
│               └── terminal.trt
├── boot/
│   ├── README.md
│   ├── boot.S
│   ├── config.c
│   ├── editor.c
│   ├── editor.h
│   ├── elf.h
│   ├── iso9660.h
│   ├── kbd.c
│   ├── kbd.h
│   ├── link.ld
│   ├── mbr.S
│   ├── menu.c
│   ├── menu.h
│   ├── multiboot.c
│   ├── multiboot.h
│   ├── options.h
│   ├── platform.c
│   ├── qemu.c
│   ├── qemu.h
│   ├── text.c
│   ├── text.h
│   ├── util.c
│   ├── util.h
│   └── video.c
├── build/
│   ├── aarch64.mk
│   └── x86_64.mk
├── kernel/
│   ├── arch/
│   │   ├── aarch64/
│   │   │   ├── arch.c
│   │   │   ├── bootstub/
│   │   │   │   ├── bootstrap.S
│   │   │   │   ├── link.ld
│   │   │   │   └── main.c
│   │   │   ├── context.S
│   │   │   ├── dtb.c
│   │   │   ├── entry.S
│   │   │   ├── fwcfg.c
│   │   │   ├── gic.c
│   │   │   ├── irq.S
│   │   │   ├── link.ld
│   │   │   ├── main.c
│   │   │   ├── mmu.c
│   │   │   ├── pl011.c
│   │   │   ├── rpi.c
│   │   │   ├── rpi400/
│   │   │   │   ├── fbterm.c
│   │   │   │   ├── link.ld
│   │   │   │   ├── main.c
│   │   │   │   └── start.S
│   │   │   ├── rpi_miniuart.c
│   │   │   ├── smp.c
│   │   │   ├── traceback.c
│   │   │   └── virtio.c
│   │   └── x86_64/
│   │       ├── bootstrap.S
│   │       ├── cmos.c
│   │       ├── gdt.c
│   │       ├── idt.c
│   │       ├── irq.S
│   │       ├── link.ld
│   │       ├── main.c
│   │       ├── mmu.c
│   │       ├── pic.c
│   │       ├── pit.c
│   │       ├── ports.c
│   │       ├── ps2hid.c
│   │       ├── serial.c
│   │       ├── smp.c
│   │       └── user.c
│   ├── audio/
│   │   └── snd.c
│   ├── binfmt.c
│   ├── generic.c
│   ├── misc/
│   │   ├── args.c
│   │   ├── assert.c
│   │   ├── elf64.c
│   │   ├── fbterm.c
│   │   ├── gzip.c
│   │   ├── hashmap.c
│   │   ├── kprintf.c
│   │   ├── ksym.c
│   │   ├── list.c
│   │   ├── malloc.c
│   │   ├── pci.c
│   │   ├── ringbuffer.c
│   │   ├── string.c
│   │   ├── tokenize.c
│   │   └── tree.c
│   ├── net/
│   │   ├── arp.c
│   │   ├── eth.c
│   │   ├── ipv4.c
│   │   ├── loop.c
│   │   ├── netif.c
│   │   └── socket.c
│   ├── sys/
│   │   ├── mutex.c
│   │   ├── process.c
│   │   ├── ptrace.c
│   │   ├── shm.c
│   │   ├── signal.c
│   │   ├── syscall.c
│   │   └── version.c
│   ├── vfs/
│   │   ├── console.c
│   │   ├── packetfs.c
│   │   ├── pipe.c
│   │   ├── portio.c
│   │   ├── procfs.c
│   │   ├── ramdisk.c
│   │   ├── random.c
│   │   ├── tarfs.c
│   │   ├── tmpfs.c
│   │   ├── tty.c
│   │   ├── unixpipe.c
│   │   ├── vfs.c
│   │   └── zero.c
│   └── video/
│       └── lfbvideo.c
├── lib/
│   ├── README.md
│   ├── auth.c
│   ├── button.c
│   ├── confreader.c
│   ├── decor-fancy.c
│   ├── decorations.c
│   ├── graphics.c
│   ├── hashmap.c
│   ├── icon_cache.c
│   ├── inflate.c
│   ├── jpeg.c
│   ├── json.c
│   ├── kbd.c
│   ├── kuroko/
│   │   ├── _waitpid.c
│   │   ├── _yutani2.c
│   │   └── yutani_mainloop.krk
│   ├── list.c
│   ├── markup.c
│   ├── markup_text.c
│   ├── menu.c
│   ├── panel_appmenu.c
│   ├── panel_clock.c
│   ├── panel_date.c
│   ├── panel_logout.c
│   ├── panel_network.c
│   ├── panel_volume.c
│   ├── panel_weather.c
│   ├── panel_windowlist.c
│   ├── pex.c
│   ├── png.c
│   ├── rline.c
│   ├── rline_exp.c
│   ├── termemu.c
│   ├── text.c
│   ├── tree.c
│   └── yutani.c
├── libc/
│   ├── arch/
│   │   ├── aarch64/
│   │   │   ├── bad.c
│   │   │   ├── crt0.S
│   │   │   ├── crti.S
│   │   │   ├── crtn.S
│   │   │   ├── memcpy.c
│   │   │   ├── memset.c
│   │   │   └── setjmp.c
│   │   └── x86_64/
│   │       ├── crt0.S
│   │       ├── crti.S
│   │       ├── crtn.S
│   │       ├── math.c
│   │       ├── memcpy.c
│   │       ├── memset.c
│   │       └── setjmp.c
│   ├── assert/
│   │   └── assert.c
│   ├── ctype/
│   │   ├── _ctype.c
│   │   ├── isalnum.c
│   │   ├── isalpha.c
│   │   ├── isascii.c
│   │   ├── iscntrl.c
│   │   ├── isdigit.c
│   │   ├── isgraph.c
│   │   ├── islower.c
│   │   ├── isprint.c
│   │   ├── ispunct.c
│   │   ├── isspace.c
│   │   ├── isupper.c
│   │   ├── isxdigit.c
│   │   ├── tolower.c
│   │   └── toupper.c
│   ├── dirent/
│   │   ├── dir.c
│   │   └── mkdir.c
│   ├── dlfcn/
│   │   └── dlfcn.c
│   ├── errno/
│   │   └── errorno.c
│   ├── iconv/
│   │   └── iconv.c
│   ├── ioctl/
│   │   └── ioctl.c
│   ├── libgen/
│   │   ├── basename.c
│   │   └── dirname.c
│   ├── libintl/
│   │   └── libintl.c
│   ├── locale/
│   │   ├── localeconv.c
│   │   └── setlocale.c
│   ├── main.c
│   ├── math/
│   │   ├── bad.c
│   │   └── math.c
│   ├── poll/
│   │   └── poll.c
│   ├── pthread/
│   │   ├── pthread.c
│   │   └── pthread_rwlock.c
│   ├── pty/
│   │   └── pty.c
│   ├── pwd/
│   │   └── pwd.c
│   ├── sched/
│   │   └── sched_yield.c
│   ├── signal/
│   │   ├── kill.c
│   │   ├── raise.c
│   │   ├── sigaction.c
│   │   ├── signal.c
│   │   ├── sigpending.c
│   │   ├── sigprocmask.c
│   │   ├── sigset.c
│   │   └── sigsuspend.c
│   ├── stdio/
│   │   ├── perror.c
│   │   ├── printf.c
│   │   ├── puts.c
│   │   ├── remove.c
│   │   ├── rename.c
│   │   ├── scanf.c
│   │   ├── stdio.c
│   │   ├── tmpfile.c
│   │   └── tmpnam.c
│   ├── stdlib/
│   │   ├── abort.c
│   │   ├── atexit.c
│   │   ├── atof.c
│   │   ├── bsearch.c
│   │   ├── div.c
│   │   ├── getenv.c
│   │   ├── labs.c
│   │   ├── malloc.c
│   │   ├── mbstowcs.c
│   │   ├── mktemp.c
│   │   ├── putenv.c
│   │   ├── qsort.c
│   │   ├── rand.c
│   │   ├── realpath.c
│   │   ├── setenv.c
│   │   ├── strtod.c
│   │   ├── strtoul.c
│   │   └── system.c
│   ├── string/
│   │   ├── memmove.c
│   │   ├── str.c
│   │   ├── strerror.c
│   │   ├── strncmp.c
│   │   ├── strncpy.c
│   │   ├── strsignal.c
│   │   └── strxfrm.c
│   ├── strings/
│   │   └── strcasecmp.c
│   ├── sys/
│   │   ├── fswait.c
│   │   ├── mount.c
│   │   ├── network.c
│   │   ├── ptrace.c
│   │   ├── reboot.c
│   │   ├── shm.c
│   │   ├── sysfunc.c
│   │   ├── uname.c
│   │   └── wait.c
│   ├── time/
│   │   ├── clock.c
│   │   ├── clock_gettime.c
│   │   ├── ctime.c
│   │   ├── gettimeofday.c
│   │   ├── localtime.c
│   │   ├── settimeofday.c
│   │   ├── strftime.c
│   │   ├── time.c
│   │   └── times.c
│   ├── unistd/
│   │   ├── access.c
│   │   ├── alarm.c
│   │   ├── chdir.c
│   │   ├── chmod.c
│   │   ├── chown.c
│   │   ├── close.c
│   │   ├── creat.c
│   │   ├── dup2.c
│   │   ├── execvp.c
│   │   ├── exit.c
│   │   ├── fcntl.c
│   │   ├── fork.c
│   │   ├── fstat.c
│   │   ├── getcwd.c
│   │   ├── getegid.c
│   │   ├── geteuid.c
│   │   ├── getgid.c
│   │   ├── getgroups.c
│   │   ├── getlogin.c
│   │   ├── getopt.c
│   │   ├── getopt_long.c
│   │   ├── getpgrp.c
│   │   ├── getpid.c
│   │   ├── getuid.c
│   │   ├── getwd.c
│   │   ├── hostname.c
│   │   ├── isatty.c
│   │   ├── link.c
│   │   ├── lseek.c
│   │   ├── open.c
│   │   ├── pathconf.c
│   │   ├── pipe.c
│   │   ├── pread.c
│   │   ├── pwrite.c
│   │   ├── read.c
│   │   ├── readlink.c
│   │   ├── rmdir.c
│   │   ├── sbrk.c
│   │   ├── setgid.c
│   │   ├── setgroups.c
│   │   ├── setpgid.c
│   │   ├── setsid.c
│   │   ├── setuid.c
│   │   ├── sleep.c
│   │   ├── stat.c
│   │   ├── statcompat.c
│   │   ├── symlink.c
│   │   ├── sync.c
│   │   ├── truncate.c
│   │   ├── ttyname.c
│   │   ├── umask.c
│   │   ├── unlink.c
│   │   ├── usleep.c
│   │   └── write.c
│   ├── utime/
│   │   └── utime.c
│   └── wchar/
│       ├── wcscat.c
│       ├── wcscmp.c
│       ├── wcscpy.c
│       ├── wcslen.c
│       ├── wcsncpy.c
│       ├── wcstok.c
│       ├── wcstol.c
│       └── wcwidth.c
├── linker/
│   ├── README.md
│   ├── link.ld
│   └── linker.c
├── modules/
│   ├── ac97.c
│   ├── ahci.c
│   ├── ata.c
│   ├── dospart.c
│   ├── e1000.c
│   ├── es1371.c
│   ├── ext2.c
│   ├── hda.c
│   ├── i965.c
│   ├── iso9660.c
│   ├── pcspkr.c
│   ├── piix4.c
│   ├── test.c
│   ├── vbox.c
│   ├── vmware.c
│   └── xhci.c
└── util/
    ├── __init__.krk
    ├── activate.sh
    ├── arch.sh
    ├── auto-dep.krk
    ├── bochsrc.txt
    ├── build-in-docker-aarch64.sh
    ├── build-in-docker.sh
    ├── build-toolchain.sh
    ├── createramdisk.py
    ├── docker/
    │   ├── Dockerfile
    │   └── README.md
    ├── gen_wcwidth.krk
    ├── generate-etc-issue.sh
    ├── generate-etc-os-release.sh
    ├── generate-release-notes.sh
    ├── gensym.krk
    ├── init.krk
    ├── libm.c
    ├── make-version
    ├── make_mbr.krk
    ├── mkdisk.sh
    ├── update-extents.krk
    └── valid-modules.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
github: [klange]


================================================
FILE: .github/SECURITY.md
================================================
# Reporting Vulnerabilities and Exploits

As ToaruOS is not intended for serious real-world use, responsible disclosure should not typically be necessary: Issue reports for security vulnerabilities should be filed [directly on Github as regular issues](https://github.com/klange/toaruos/issues). There may be exceptions to this, eg. if you discover a remote exploit that could affect casual users or impacts the host system during the build process.

Reports are greatly appreciated, but my bandwidth to work on the OS is limited. While I will generally try to spend some time on quick fixes for issues that adversely affect the behavior of benign software, I may never get around to addressing vulnerabilities which require more careful exploits - but, please do still report these. As an exception to my general contribution guidelines, I am open to accepting unprompted code contributions related to resolving security issues.

## For Users

Beyond the usual boilerplate about the software being provided "as is" and "without warranty", potential users should understand that ToaruOS is not meant to be "used" at all. ToaruOS is intended as an educational tool - it is meant to be studied. While users are encouraged to run the OS in a virtual machine to that end, proper precautions should be taken. If the OS is exposed to untrusted users, it should be properly isolated and firewalled. The use of virtual machine hosts which employ tunnel devices when on an untrusted network is highly discouraged.

## For CTF Operators

ToaruOS has been used in a handful of CTF competitions, which I find quite neat. If you are operating a CTF and have identified an existing vulnerability you hope competitors will find and exploit, I am happy to be informed ahead of time and won't spoil things.

Additionally, as a recommendation to CTF operators, there are many known TOCTOU vulnerabilities in ToaruOS that are only exploitable when SMP is enabled. These kinds of issues are likely to stick around for a while, so consider disabling SMP to make the attack surface smaller and more interesting.


================================================
FILE: .github/workflows/aarch64.yml
================================================
on: [push, workflow_dispatch]
name: QEMU AArch64 virt
jobs:
  build-image:
    runs-on: ubuntu-latest
    steps:
      - name: Clone Repository
        uses: actions/checkout@v2
        with:
            fetch-depth: 0
      - name: Clone Kuroko
        uses: actions/checkout@v2
        with:
          repository: kuroko-lang/kuroko
          path: kuroko
      - name: Checkout Kuroko
        run: git submodule update --init kuroko
      - name: Pull Builder Image
        run: docker pull toaruos/build-tools:aarch64
      - name: Run Builder
        run: docker run -v ${GITHUB_WORKSPACE}:/root/misaka -w /root/misaka -e LANG=C.UTF-8 -t toaruos/build-tools:aarch64 util/build-in-docker-aarch64.sh
      - name: Upload virt Artifacts
        uses: actions/upload-artifact@v4
        with:
          name: aarch64-virt
          path: |
            misaka-kernel
            ramdisk.igz
            bootstub
      - name: Upload rpi400 Artifacts
        uses: actions/upload-artifact@v4
        with:
          name: aarch64-rpi400
          path: |
            kernel8.img


================================================
FILE: .github/workflows/x86_64.yml
================================================
on: [push, workflow_dispatch]
name: x86-64 CD Image
jobs:
  build-image:
    runs-on: ubuntu-latest
    steps:
      - name: Clone Repository
        uses: actions/checkout@v2
        with:
            fetch-depth: 0
      - name: Clone Kuroko
        uses: actions/checkout@v2
        with:
          repository: kuroko-lang/kuroko
          path: kuroko
      - name: Checkout Kuroko
        run: git submodule update --init kuroko
      - name: Pull Builder Image
        run: docker pull toaruos/build-tools:1.99.x
      - name: Run Builder
        run: docker run -v ${GITHUB_WORKSPACE}:/root/misaka -w /root/misaka -e LANG=C.UTF-8 -t toaruos/build-tools:1.99.x util/build-in-docker.sh
      - name: Upload Branch Image
        uses: actions/upload-artifact@v4
        with:
          name: build
          path: |
            image.iso
      - name: Draft Release notes
        if: startsWith(github.ref, 'refs/tags/v')
        run: bash util/generate-release-notes.sh > notes.md
      - name: Create Release
        if: startsWith(github.ref, 'refs/tags/v')
        uses: actions/create-release@v1
        id: create_release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: ToaruOS ${{ github.ref }}
          body_path: ./notes.md
          draft: true
      - name: Upload Release Image
        if: startsWith(github.ref, 'refs/tags/v')
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./image.iso
          asset_name: image.iso
          asset_content_type: application/x-iso9660-image


================================================
FILE: .gitignore
================================================
*.aux
*.idx
*.ilg
*.ind
*.log
*.o
*.a
*.out
*.pdf
*.so
*.swp
*.swn
*.toc
*.ko
*.pcap
.gdb_history
/ramdisk.tar
/ramdisk.igz
/misaka-kernel.64
/misaka-kernel
/kernel/symbols.S
/util/build
/util/local
/util/cross
/base/bin/*
/base/etc/issue
/base/etc/os-release
/base/usr/bin/*
/base/usr/lib/*
/base/lib/kuroko/*
/base/usr/share/games/doom
/.make/
/cdrom
/fatbase
/image.iso
/boot/mbr.sys
/bootstub
/.arch
/kernel8.img
/kernel8.img.elf


================================================
FILE: .gitmodules
================================================
[submodule "util/binutils-gdb"]
	path = util/binutils-gdb
	url = ../../toaruos/binutils-gdb
[submodule "util/gcc"]
	path = util/gcc
	url = ../../toaruos/gcc
[submodule "kuroko"]
	path = kuroko
	url = ../../kuroko-lang/kuroko


================================================
FILE: .mailmap
================================================
K. Lange <klange@toaruos.org>
K. Lange <klange@toaruos.org> <klange@dakko.us>
K. Lange <klange@toaruos.org> <k@dakko.us>
K. Lange <klange@toaruos.org> <kevin.lange@dakko.us>
K. Lange <klange@toaruos.org> <kevin.lange@mujin.co.jp>
K. Lange <klange@toaruos.org> <kevin.lange@phpwnage.com>
K. Lange <klange@toaruos.org> <klange@yelp.com>
Markus Schober <schober1@bobrife.acm.uiuc.edu> <schober1@illinois.edu>
Mike Gerow <gerow@mgerow.com> <gerow.mike@gmail.com>
Tianyi Wang <wang103@illinois.edu> <tianyi@Rin.(none)>
Jozef Nagy <jozefnagy1133@yahoo.com> <38380751+jozefnagyoff@users.noreply.github.com>
Mai M. <mathew1800@gmail.com>
Ofek Lavie <ofeklavie@gmail.com>


================================================
FILE: AUTHORS
================================================
Maintainer and Author:

    K. Lange

Major Contributors:

    Mike Gerow
    Dale Weiler
    Matt White
    Markus Schober

Other Contributors:

    Adam DiCarlo
    David Hayman
    Fabien Siron
    Gil Mendes
    Ivailo Monev
    Josh Kilmer
    Lioncash
    Noah Rosamilia
    Ofek
    Patrick Lucas
    Peter Harliman Liem
    Shawn Anastasio
    Steve Jenson
    Tianyi Wang
    Tyler Bindon


================================================
FILE: LICENSE
================================================

University of Illinois/NCSA Open Source License

Copyright (c) 2011-2022 K Lange, et al. (hereafter [fullname]). All rights reserved.

Developed by: ToaruOS (hereafter [project])

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal with the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimers.

* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimers in the
  documentation and/or other materials provided with the distribution.

* Neither the names of [fullname], [project] nor the names of its
  contributors may be used to endorse or promote products derived from
  this Software without specific prior written permission.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
THE SOFTWARE.


================================================
FILE: Makefile
================================================
# ToaruOS 2.0 root Makefile
TOOLCHAIN=util
BASE=base
export PATH := $(shell $(TOOLCHAIN)/activate.sh)

ARCH ?= $(shell $(TOOLCHAIN)/arch.sh)

include build/${ARCH}.mk

# Cross compiler binaries
CC = ${TARGET}-gcc
NM = ${TARGET}-nm
CXX= ${TARGET}-g++
AR = ${TARGET}-ar
AS = ${TARGET}-as
OC = ${TARGET}-objcopy
STRIP= ${TARGET}-strip

# CFLAGS for kernel objects and modules
KERNEL_CFLAGS  = -ffreestanding -O2 -std=gnu11 -g -static
KERNEL_CFLAGS += -Wall -Wextra -Wno-unused-function -Wno-unused-parameter -Wstrict-prototypes
KERNEL_CFLAGS += -pedantic -Wwrite-strings ${ARCH_KERNEL_CFLAGS}

# Defined constants for the kernel
KERNEL_CFLAGS += -D_KERNEL_ -DKERNEL_ARCH=${ARCH}
KERNEL_CFLAGS += -DKERNEL_GIT_TAG=$(shell util/make-version)

# Automatically find kernel sources from relevant paths
KERNEL_OBJS =  $(patsubst %.c,%.o,$(wildcard kernel/*.c))
KERNEL_OBJS += $(patsubst %.c,%.o,$(wildcard kernel/*/*.c))
KERNEL_OBJS += $(patsubst %.c,%.o,$(wildcard kernel/arch/${ARCH}/*.c))

# Assembly sources only come from the arch-dependent directory
KERNEL_ASMOBJS  = $(filter-out kernel/symbols.o,$(patsubst %.S,%.o,$(wildcard kernel/arch/${ARCH}/*.S)))

# These sources are used to determine if we should update symbols.o
KERNEL_SOURCES  = $(wildcard kernel/*.c) $(wildcard kernel/*/*.c) $(wildcard kernel/${ARCH}/*/*.c)
KERNEL_SOURCES += $(wildcard kernel/arch/${ARCH}/*.S)

# Kernel modules are one file = one module; if you want to build more complicated
# modules, you could potentially use `ld -r` to turn multiple source objects into
# a single relocatable object file.
ARCH_ENABLED_MODS = $(shell util/valid-modules.sh $(ARCH))
MODULES = $(patsubst modules/%.c,$(BASE)/mod/%.ko,$(foreach mod,$(ARCH_ENABLED_MODS),modules/$(mod).c))

EMU = qemu-system-${ARCH}

APPS=$(patsubst apps/%.c,%,$(wildcard apps/*.c))
APPS_X=$(foreach app,$(APPS),$(BASE)/bin/$(app))
APPS_Y=$(foreach app,$(APPS),.make/$(app).mak)
APPS_SH=$(patsubst apps/%.sh,%.sh,$(wildcard apps/*.sh))
APPS_SH_X=$(foreach app,$(APPS_SH),$(BASE)/bin/$(app))
APPS_KRK=$(patsubst apps/%.krk,%.krk,$(wildcard apps/*.krk))
APPS_KRK_X=$(foreach app,$(APPS_KRK),$(BASE)/bin/$(app))

LIBS=$(patsubst lib/%.c,%,$(wildcard lib/*.c))
LIBS_X=$(foreach lib,$(LIBS),$(BASE)/lib/libtoaru_$(lib).so)
LIBS_Y=$(foreach lib,$(LIBS),.make/$(lib).lmak)

KRK_MODS = $(patsubst kuroko/src/modules/module_%.c,$(BASE)/lib/kuroko/%.so,$(wildcard kuroko/src/modules/module_*.c))
KRK_MODS += $(patsubst kuroko/modules/%,$(BASE)/lib/kuroko/%,$(wildcard kuroko/modules/*.krk kuroko/modules/*/*.krk kuroko/modules/*/*/.krk kuroko/modules/*/*/*.krk))
KRK_MODS += $(patsubst lib/kuroko/%,$(BASE)/lib/kuroko/%,$(wildcard lib/kuroko/*.krk))
KRK_MODS_X = $(patsubst lib/kuroko/%.c,$(BASE)/lib/kuroko/%.so,$(wildcard lib/kuroko/*.c))
KRK_MODS_Y = $(patsubst lib/kuroko/%.c,.make/%.kmak,$(wildcard lib/kuroko/*.c))

CFLAGS= -O2 -std=gnu11 -I. -Iapps -fplan9-extensions -Wall -Wextra -Wno-unused-parameter ${ARCH_USER_CFLAGS}
LIBC_CFLAGS = -O2 -std=gnu11 -ffreestanding -Wall -Wextra -Wno-unused-parameter ${ARCH_USER_CFLAGS}

LIBC_OBJS  = $(patsubst %.c,%.o,$(wildcard libc/*.c))
LIBC_OBJS += $(patsubst %.c,%.o,$(wildcard libc/*/*.c))
LIBC_OBJS += $(patsubst %.c,%.o,$(wildcard libc/arch/${ARCH}/*.c))

GCC_SHARED = $(BASE)/usr/lib/libgcc_s.so.1 $(BASE)/usr/lib/libgcc_s.so

CRTS  = $(BASE)/lib/crt0.o $(BASE)/lib/crti.o $(BASE)/lib/crtn.o

LC = $(BASE)/lib/libc.so $(GCC_SHARED)

.PHONY: all system clean run shell

$(BASE)/mod/%.ko: modules/%.c | dirs
	${CC} -c ${KERNEL_CFLAGS} -fno-pie -mcmodel=large  -o $@ $<

ramdisk.igz: $(wildcard $(BASE)/* $(BASE)/*/* $(BASE)/*/*/* $(BASE)/*/*/*/* $(BASE)/*/*/*/*/*) $(APPS_X) $(LIBS_X) $(KRK_MODS_X) $(BASE)/bin/kuroko $(BASE)/lib/ld.so $(BASE)/lib/libm.so $(APPS_KRK_X) $(KRK_MODS) $(APPS_SH_X) $(MODULES) $(BASE)/etc/issue $(BASE)/etc/os-release
	python3 util/createramdisk.py

$(BASE)/etc/issue: kernel/sys/version.c util/generate-etc-issue.sh
	sh util/generate-etc-issue.sh > $@

$(BASE)/etc/os-release: kernel/sys/version.c util/generate-etc-os-release.sh
	sh util/generate-etc-os-release.sh > $@

KRK_SRC = $(sort $(wildcard kuroko/src/*.c))
$(BASE)/bin/kuroko: $(KRK_SRC) $(CRTS)  lib/rline.c | $(LC)
	$(CC) $(CFLAGS) -o $@ -Wl,--export-dynamic -Ikuroko/src $(KRK_SRC) lib/rline.c

$(BASE)/lib/kuroko/%.so: kuroko/src/modules/module_%.c| dirs $(LC)
	$(CC) $(CFLAGS) -shared -fPIC -Ikuroko/src -o $@ $<

$(BASE)/lib/kuroko/%.krk: kuroko/modules/%.krk | dirs
	mkdir -p $(dir $@)
	cp $< $@

$(BASE)/lib/kuroko/%.krk: lib/kuroko/%.krk | dirs
	mkdir -p $(dir $@)
	cp $< $@

$(BASE)/lib/libkuroko.so: $(KRK_SRC) | $(LC)
	$(CC) -O2 -shared -fPIC -Ikuroko/src -o $@ $(filter-out kuroko/src/kuroko.c,$(KRK_SRC))

$(BASE)/lib/ld.so: linker/linker.c $(BASE)/lib/libc.a | dirs $(LC)
	$(CC) -g -static -Wl,-static $(CFLAGS) -z max-page-size=0x1000 -o $@ -Os -T linker/link.ld $<

kernel/sys/version.o: ${KERNEL_SOURCES}

kernel/symbols.o: ${KERNEL_ASMOBJS} ${KERNEL_OBJS} util/gensym.krk
	-rm -f kernel/symbols.o
	${NM} -g -f p ${KERNEL_ASMOBJS} ${KERNEL_OBJS} | kuroko util/gensym.krk > kernel/symbols.S
	${CC} -c kernel/symbols.S -o $@

kernel/%.o: kernel/%.S
	${CC} -c $< -o $@

HEADERS = $(wildcard base/usr/include/kernel/*.h) $(wildcard base/usr/include/kernel/*/*.h)

kernel/%.o: kernel/%.c ${HEADERS}
	${CC} ${KERNEL_CFLAGS} -nostdlib -g -Iinclude -c -o $@ $<

clean:
	-rm -f ${KERNEL_ASMOBJS}
	-rm -f ${KERNEL_OBJS} $(MODULES)
	-rm -f kernel/symbols.o kernel/symbols.S misaka-kernel misaka-kernel.64
	-rm -f ramdisk.tar ramdisk.igz 
	-rm -f $(APPS_Y) $(LIBS_Y) $(KRK_MODS_Y) $(KRK_MODS)
	-rm -f $(APPS_X) $(LIBS_X) $(KRK_MODS_X) $(APPS_KRK_X) $(APPS_SH_X)
	-rm -f $(BASE)/lib/crt0.o $(BASE)/lib/crti.o $(BASE)/lib/crtn.o
	-rm -f $(BASE)/lib/libc.so $(BASE)/lib/libc.a
	-rm -f $(LIBC_OBJS) $(BASE)/lib/ld.so $(BASE)/lib/libkuroko.so $(BASE)/lib/libm.so
	-rm -f $(BASE)/bin/kuroko
	-rm -f $(GCC_SHARED)
	-rm -f boot/efi/*.o boot/bios/*.o

libc/%.o: libc/%.c base/usr/include/syscall.h 
	$(CC) ${LIBC_CFLAGS} -fPIC -c -o $@ $<

.PHONY: libc
libc: $(BASE)/lib/libc.a $(BASE)/lib/libc.so

$(BASE)/lib/libc.a: ${LIBC_OBJS} $(CRTS)
	$(AR) cr $@ $(LIBC_OBJS)

$(BASE)/lib/libc.so: ${LIBC_OBJS} | $(CRTS)
	${CC} -nodefaultlibs -shared -fPIC -o $@ $^ -lgcc

$(BASE)/lib/crt%.o: libc/arch/${ARCH}/crt%.S
	${AS} -o $@ $<

$(BASE)/usr/lib/%: $(TOOLCHAIN)/local/${TARGET}/lib/% | dirs
	cp -a $< $@
	-$(STRIP) $@

$(BASE)/lib/libm.so: util/libm.c
	$(CC) -shared -nostdlib -fPIC -o $@ $<

$(BASE)/dev:
	mkdir -p $@
$(BASE)/tmp:
	mkdir -p $@
$(BASE)/proc:
	mkdir -p $@
$(BASE)/bin:
	mkdir -p $@
$(BASE)/lib:
	mkdir -p $@
$(BASE)/cdrom:
	mkdir -p $@
$(BASE)/var:
	mkdir -p $@
$(BASE)/mod:
	mkdir -p $@
$(BASE)/lib/kuroko:
	mkdir -p $@
$(BASE)/usr/lib:
	mkdir -p $@
$(BASE)/usr/bin:
	mkdir -p $@
boot/efi:
	mkdir -p $@
boot/bios:
	mkdir -p $@
fatbase/efi/boot:
	mkdir -p $@
cdrom:
	mkdir -p $@
.make:
	mkdir -p .make
dirs: $(BASE)/dev $(BASE)/tmp $(BASE)/proc $(BASE)/bin $(BASE)/lib $(BASE)/cdrom $(BASE)/usr/lib $(BASE)/usr/bin $(BASE)/lib/kuroko cdrom $(BASE)/var fatbase/efi/boot .make $(BASE)/mod boot/efi boot/bios

ifeq (,$(findstring clean,$(MAKECMDGOALS))$(findstring $(BUILD_KRK),$(MAKECMDGOALS)))
-include ${APPS_Y}
-include ${LIBS_Y}
-include ${KRK_MODS_Y}
endif

.make/%.lmak: lib/%.c util/auto-dep.krk | dirs $(CRTS)
	kuroko util/auto-dep.krk --makelib $< > $@

.make/%.mak: apps/%.c util/auto-dep.krk | dirs $(CRTS)
	kuroko util/auto-dep.krk --make $< > $@

.make/%.kmak: lib/kuroko/%.c util/auto-dep.krk | dirs
	kuroko util/auto-dep.krk --makekurokomod $< > $@

$(BASE)/bin/%.sh: apps/%.sh
	cp $< $@
	chmod +x $@

$(BASE)/bin/%.krk: apps/%.krk
	cp $< $@
	chmod +x $@

.PHONY: libs
libs: $(LIBS_X)

.PHONY: apps
apps: $(APPS_X)

SOURCE_FILES  = $(wildcard kernel/*.c kernel/*/*.c kernel/*/*/*.c kernel/*/*/*/*.c)
SOURCE_FILES += $(wildcard apps/*.c linker/*.c libc/*.c libc/*/*.c lib/*.c lib/kuroko/*.c)
SOURCE_FILES += $(wildcard kuroko/src/*.c kuroko/src/*.h kuroko/src/*/*.c kuroko/src/*/*.h)
SOURCE_FILES += $(wildcard $(BASE)/usr/include/*.h $(BASE)/usr/include/*/*.h $(BASE)/usr/include/*/*/*.h)
tags: $(SOURCE_FILES)
	ctags -f tags $(SOURCE_FILES)



================================================
FILE: README.md
================================================
# ToaruOS

ToaruOS is a "complete" operating system for x86-64 PCs and experimental support for ARMv8.

While many independent, hobby, and research OSes aim to experiment with new designs, ToaruOS is intended as an educational resource, providing a representative microcosm of functionality found in major desktop operating systems.

The OS includes a kernel, bootloader, dynamic shared object linker, C standard library, its own composited windowing system, a dynamic bytecode-compiled programming language, advanced code editor, and dozens of other utilities and example applications.

There are no external runtime dependencies and all required source code, totalling roughly 100k lines of (primarily) C, is included in this repository, save for [Kuroko](https://github.com/kuroko-lang/kuroko), which lives separately.

![Screenshot](https://klange.dev/s/Screenshot%20from%202021-12-06%2011-38-12.png)
*Demonstration of ToaruOS's UI and some applications.*

## History

> I have been working on ToaruOS for over a decade now, and my goals have changed over the years.
>
> When I first started the project in December 2010, my aim was to "learn by doing" - studying Unix-like systems by making one from scratch.
> I had been a contributor to Compiz, one of the first widely-used compositing window managers for X11, a few years prior, and somewhat naturally ToaruOS gained a GUI built on similar concepts early on.
>
> For its original 1.0 release in 2015, ToaruOS was not the "completely from scratch" OS it has since become.
> Newlib provided the libc, and the GUI was built on Cairo, libpng, and Freetype.
> In the middle of 2018, I started a new project to replace these third-party components, which was eventually completed and merged to become ToaruOS 1.6.
>
> Through out the project, ToaruOS has also attracted quite a few beginner OS developers who have tried to use it as a reference.
> ToaruOS's kernel, however, was a source of personal embarrassment for me, and in April 2021, after a long hiatus, I began work on a new one.
> The result was Misaka: a new 64-bit, SMP-enabled kernel. Misaka was merged in May and started the 1.99 series of beta releases leading up to ToaruOS 2.0.

## Features

- **Dynamically linked userspace** with shared libraries and `dlopen`.
- **Composited graphical UI** with software acceleration and a late-2000s design inspiration.
- **VM integration** for absolute mouse and automatic display sizing in VirtualBox and VMware Workstation.
- **Unix-like terminal interface** including a feature-rich terminal emulator and several familiar utilities.
- **Optional third-party ports** including GCC 10.3, Binutils, SDL1.2, Quake, and more.

### Notable Components

- **Misaka** (kernel), [kernel/](kernel/), a hybrid modular kernel, and the core of the operating system.
- **Yutani** (window compositor), [apps/compositor.c](apps/compositor.c), manages window buffers, layout, and input routing.
- **Bim** (text editor), [apps/bim.c](apps/bim.c), is a Vim-inspired editor with syntax highlighting.
- **Terminal**, [apps/terminal.c](apps/terminal.c), xterm-esque terminal emulator with 24-bit color support.
- **ld.so** (dynamic linker/loader), [linker/linker.c](linker/linker.c), loads dynamically-linked ELF binaries.
- **Esh** (shell), [apps/esh.c](apps/esh.c), supports pipes, redirections, variables, etc.
- **Kuroko** (interpreter), [kuroko/](https://kuroko-lang.github.io/), a dynamic bytecode-compiled programming language.

## Current Goals

The following projects are currently in progress:

- **Rewrite the network stack** for greater throughput, stability, and server support.
- **Improve SMP performance** with better scheduling and smarter userspace synchronization functions.
- **Support more hardware** with new device drivers for AHCI, USB, virtio devices, etc.
- **Bring back ports** from ToaruOS "Legacy", like muPDF and Mesa.
- **Improve POSIX coverage** especially in regards to signals, synchronization primitives, as well as by providing more common utilities.
- **Continue to improve the C library** which remains quite incomplete compared to Newlib and is a major source of issues with bringing back old ports.
- **Replace third-party development tools** to get the OS to a state where it is self-hosting with just the addition of a C compiler.
- **Implement a C compiler toolchain** in [toarucc](https://github.com/klange/toarucc).

## Building / Installation

### Building With Docker

General users hoping to build ToaruOS from source are recommended to fork the repository on Github and make use of the Github CI pipeline.

For those looking to build locally on an appropriately configured Linux host with Docker, a build container is available. The ToaruOS repository should be used as a bind mount at `/root/misaka` and `util/build-in-docker.sh` can be run within this container to complete the compilation process:

    git clone https://github.com/klange/toaruos
    cd toaruos
    git submodule update --init kuroko
    docker pull toaruos/build-tools:1.99.x
    docker run -v `pwd`:/root/misaka -w /root/misaka -e LANG=C.UTF-8 -t toaruos/build-tools:1.99.x util/build-in-docker.sh

After building like this, you can run the various utility targets (`make run`, etc.). Try `make shell` to run a ToaruOS shell using a serial port with QEMU.

### Build Process Internals

The `Makefile` uses a Kuroko tool, `auto-dep.krk`, to generate additional Makefiles for the userspace applications and libraries, automatically resolving dependencies based on `#include` directives.

In an indeterminate order, the C library, kernel, userspace librares and applications are built, combined into a compressed archive for use as a ramdisk, and then packaged into an ISO9660 filesystem image.

### Project Layout

- **apps** - Userspace applications, all first-party.
- **base** - Ramdisk root filesystem staging directory. Includes C headers in `base/usr/include`, as well as graphical resources for the compositor and window decorator.
- **boot** - BIOS and EFI loader with interactive menus.
- **build** - Auxiliary build scripts for platform ports.
- **kernel** - The Misaka kernel.
- **kuroko** - Submodule checkout of the Kuroko interpreter.
- **lib** - Userspace libraries.
- **libc** - C standard library implementation.
- **linker** - Userspace dynamic linker/loader, implements shared library support.
- **modules** - Loadable driver modules for the kernel.
- **util** - Utility scripts, staging directory for the toolchain (binutils/gcc).
- **.make** - Generated Makefiles.

### Filesystem Layout

The root filesystem is set up as follows:

- `bin`: First-party applications.
- `cdrom`: Mount point for the CD, if available.
- `dev`: Virtual device directory, generated by the kernel.
  - `net`: Network interface devices.
  - `pex`: Packet Exchange hub, lists accessible IPC services.
  - `pts`: PTY secondaries, endpoints for TTYs.
- `etc`: Configuration files, startup scripts.
- `home`: User directories.
- `lib`: First-party libraries
  - `kuroko`: Kuroko modules.
- `mod`: Loadable kernel modules.
- `proc`: Virtual files that present kernel state.
  - `1`, etc.: Virtual files with status information for individual processes.
- `src`: Source files, see "Project Layout" section above.
- `tmp`: Mounted as a read/write tmpfs normally.
- `usr`: Userspace resources
  - `bin`: Third-party applications, normally empty until packages are installed.
  - `include`: Header files, including potentially ones from third-party packages.
  - `lib`: Third-party libraries. Should have `libgcc_s.so` by default.
  - `share`: Various resources.
    - `bim`: Syntax highlighting and themes for the text editor.
    - `cursor`: Mouse cursor sprites.
    - `fonts`: TrueType font files. Live CDs ship with Deja Vu Sans.
    - `games`: Dumping ground for game-related resource files, like Doom wads.
    - `help`: Documentation files for the Help Browser application.
    - `icons`: PNG icons, divided into further directories by size.
    - `ttk`: Spritesheet resources for the window decorator and widget library.
    - `wallpapers`: JPEG wallpapers.
- `var`: Runtime files, including package manager manifest cache, PID files, some lock files, etc.

## Running ToaruOS

### VirtualBox and VMware Workstation

The best end-user experience with ToaruOS will be had in either of these virtual machines, as ToaruOS has support for their automatic display sizing and absolute mouse positioning.

Set up a new VM for an "other" 64-bit guest, supply it with at least 1GiB of RAM, attach the CD image, remove or ignore any hard disks, and select an Intel Gigabit NIC. Two or more CPUs are recommended, as well.

![VirtualBox screenshot](https://klange.dev/s/Screenshot%20from%202021-12-06%2011-39-27.png)
*ToaruOS running in VirtualBox.*

![VMware screenshot](https://klange.dev/s/Screenshot%20from%202021-12-06%2011-41-17.png)
*ToaruOS running in VMware Workstation Player.*

By default, the bootloader will pass a flag to the VirtualBox device driver to disable "Seamless" support as the implementation has a performance overhead. To enable Seamless mode, use the bootloader menu to check the "VirtualBox Seamless" option before booting. The menu also has options to disable automatic guest display sizing if you experience issues with this feature.

### QEMU

Most development of ToaruOS happens in QEMU, as it provides the most flexibility in hardware and the best debugging experience. A recommended QEMU command line in an Ubuntu 20.04 host is:

```
qemu-system-x86_64 -enable-kvm -m 1G -device AC97 -cdrom image.iso -smp 2
```

Replace `-enable-kvm` with `-accel hvm` or `-accel haxm` as appropriate on host platforms without KVM, or remove it to try under QEMU's TCG software emulation.

Note that QEMU command line options are not stable and these flags may produce warnings in newer versions.

The option `-M q35` will replace the PIIX chipset emulation with a newer one, which has the side effect of switching the IDE controller for a SATA one. This can result in faster boot times at the expense of ToaruOS not being able to read its own CD at runtime until I get around to finishing my AHCI driver.

### Other

ToaruOS has been successfully tested on real hardware. If the native BIOS or EFI loaders fail to function, try booting with Grub. ToaruOS complies with the "Multiboot" and "Multiboot 2" specs so it may be loaded with either the `multiboot` or `multiboot2` commands as follows:

```
multiboot2 /path/to/misaka-kernel root=/dev/ram0 migrate vid=auto start=live-session
module2 /path/to/ramdisk.igz
set gfxpayload=keep
```

![Native photo](https://klange.dev/s/IMG_8387.jpg)
*ToaruOS running natively from a USB stick on a ThinkPad T410.*

## License

All first-party parts of ToaruOS are made available under the terms of the University of Illinois / NCSA License, which is a BSD-style permissive license.
Unless otherwise specified, this is the original and only license for all files in this repository - just because a file does not have a copyright header does not mean it isn't under this license.
ToaruOS is intended as an educational reference, and I encourage the use of my code, but please be sure you follow the requirements of the license.
You may redistribute code under the NCSA license, as well as make modifications to the code and sublicense it under other terms (such as the GPL, or a proprietary license), but you must always include the copyright notice specified in the license as well as make the full text of the license (it's only a couple paragraphs) available to end-users.

While most of ToaruOS is written entirely by myself, be sure to include other authors where relevant, such as with [Mike's audio subsystem](https://github.com/klange/toaruos/blob/master/kernel/audio/snd.c) or [Dale's string functions](https://github.com/klange/toaruos/blob/master/kernel/misc/string.c).

Some components of ToaruOS, such as [Kuroko](https://github.com/kuroko-lang/kuroko/blob/9f6160092ecece0f2c18b63c066151cbe0ded1bb/LICENSE) or [bim](https://github.com/klange/toaruos/blob/master/apps/bim.c#L3) have different but compatible terms.

## Community

### Mirrors

ToaruOS is regularly mirrored to multiple Git hosting sites.

- Gitlab: [toaruos/toaruos](https://gitlab.com/toaruos/toaruos)
- GitHub: [klange/toaruos](https://github.com/klange/toaruos)
- Bitbucket: [klange/toaruos](https://bitbucket.org/klange/toaruos)
- ToaruOS.org: [klange/toaruos](https://git.toaruos.org/klange/toaruos)

### IRC

`#toaruos` on Libera (`irc.libera.chat`)

## FAQs

### Is ToaruOS self-hosting?

Individual applications and libraries can be built by installing the `build-essential` metapackage from the repository, which will pull in `gcc` and `binutils`.
Sources are available in the `/src` directory on the live CD in a similar layout to this repository, and the `auto-dep.krk` utility script is also available.

For building ramdisks, finalized kernels, or CD images, some components are currently unavailable.
In particular, the [build script for ramdisks](util/createramdisk.py) is still written in Python and depends on its `tarfile` module and `zlib` support.
Previously, with a capable compiler toolchain, ToaruOS 1.x was able to build its own kernel, userspace, libraries, and bootloader, and turn these into a working ISO CD image through a Python script that performed a similar function to the Makefile.

ToaruOS is not currently capable of building most of its ports, due to a lack of a proper POSIX shell and Make implementation. These are eventual goals of the project.

### Is ToaruOS a Linux distribution?

No, not at all. There is no code from Linux anywhere in ToaruOS, nor were Linux sources used as a reference material.

ToaruOS is a completely independent project, and all code in this repository - which is the entire codebase of the operating system, including its kernel, bootloaders, libraries, and applications - is original, written by myself and a handful of contributors over the course of ten years.
The complete source history, going back to when ToaruOS was nothing more than a baremetal "hello world" can be tracked through this git repository.

### When you say "complete"...

ToaruOS is complete in the sense that it covers the whole range of functionality for an OS: It is not "just a kernel" or "just a userspace".

ToaruOS is _not_ complete in the sense of being "done".

### Is ToaruOS POSIX-compliant?

While I aim to support POSIX interfaces well enough for software to be ported, strict implementation of the standard is not a major goal of the OS, and full compliance may even be undesirable.

### Are contributions accepted?

ToaruOS is a personal project, not a community project. Contributions in the form of code should be discussed in advance. Ports and other work outside of the repo, however, are a great way to help out.

You can also help by contributing to [Kuroko](https://github.com/kuroko-lang/kuroko) - which is part of why it's kept as a separate repository.


================================================
FILE: apps/about.c
================================================
/**
 * @brief about - Show an "About <Application>" dialog.
 *
 * By default, shows "About ToaruOS", suitable for use as an application
 * menu entry. Optionally, takes arguments specifying another application
 * to describe, suitable for the "Help > About" menu bar entry.
 *
 * @copyright
 * This file is part of ToaruOS and is released under the terms
 * of the NCSA / University of Illinois License - see LICENSE.md
 * Copyright (C) 2018-2019 K. Lange
 */
#include <toaru/yutani.h>
#include <toaru/graphics.h>
#include <toaru/decorations.h>
#include <toaru/menu.h>
#include <toaru/text.h>
#include <toaru/markup_text.h>

#include <sys/utsname.h>

static yutani_t * yctx;
static yutani_window_t * window = NULL;
static gfx_context_t * ctx = NULL;
static sprite_t logo;

static int32_t width = 350;
static int32_t height = 250;
static char * version_str;

static char * icon_path;
static char * title_str;
static char * version_str;
static char * copyright_str[20] = {NULL};

static int center_x(int x) {
	return (width - x) / 2;
}

static void draw_string(int y, const char * string, int mode, uint32_t color) {
	struct decor_bounds bounds;
	decor_get_bounds(window, &bounds);
	struct MarkupState * renderer = markup_setup_renderer(NULL, 0, 0, 0, 1);
	markup_set_base_font_size(renderer, 13);
	markup_set_base_state(renderer, mode);
	markup_push_string(renderer, string);
	int calcwidth = markup_finish_renderer(renderer);

	renderer = markup_setup_renderer(ctx, bounds.left_width + center_x(calcwidth), bounds.top_height + 10 + logo.height + 10 + y + 13, color, 0);
	markup_set_base_font_size(renderer, 13);
	markup_set_base_state(renderer, mode);
	markup_push_string(renderer, string);
	markup_finish_renderer(renderer);
}

static void redraw(void) {

	struct decor_bounds bounds;
	decor_get_bounds(window, &bounds);

	draw_fill(ctx, rgb(204,204,204));
	draw_sprite(ctx, &logo, bounds.left_width + center_x(logo.width), bounds.top_height + 10);

	draw_string(0, version_str, MARKUP_TEXT_STATE_BOLD, rgb(0,0,0));

	int offset = 20;

	for (char ** copy_str = copyright_str; *copy_str; ++copy_str) {
		if (**copy_str == '-') {
			offset += 10;
		} else if (**copy_str == '%') {
			draw_string(offset, *copy_str+1, 0, rgb(0,0,255));
			offset += 20;
		} else {
			draw_string(offset, *copy_str, 0, rgb(0,0,0));
			offset += 20;
		}
	}

	window->decorator_flags |= DECOR_FLAG_NO_MAXIMIZE;
	render_decorations(window, ctx, title_str);

	flip(ctx);
	yutani_flip(yctx, window);
}

static void init_default(void) {
	title_str = "About ToaruOS";
	icon_path = "/usr/share/logo_login.png";

	{
		version_str = malloc(100);
		struct utsname u;
		uname(&u);
		char * tmp = strstr(u.release, "-");
		if (tmp) {
			*tmp = '\0';
		}
		sprintf(version_str, "ToaruOS %s", u.release);
	}

	copyright_str[0] = "© 2011-2026 K. Lange, et al.";
	copyright_str[1] = "-";
	copyright_str[2] = "ToaruOS is free software released under the";
	copyright_str[3] = "NCSA/University of Illinois license.";
	copyright_str[4] = "-";
	copyright_str[5] = "%https://toaruos.org";
	copyright_str[6] = "%https://github.com/klange/toaruos";
}

void resize_finish(int w, int h) {
	yutani_window_resize_accept(yctx, window, w, h);
	reinit_graphics_yutani(ctx, window);
	struct decor_bounds bounds;
	decor_get_bounds(NULL, &bounds);
	width  = w - bounds.width;
	height = h - bounds.height;
	redraw();
	yutani_window_resize_done(yctx, window);
}

int main(int argc, char * argv[]) {
	int req_center_x, req_center_y;
	yctx = yutani_init();
	if (!yctx) {
		fprintf(stderr, "%s: failed to connect to compositor\n", argv[0]);
		return 1;
	}
	init_decorations();
	markup_text_init();

	struct decor_bounds bounds;
	decor_get_bounds(NULL, &bounds);

	window = yutani_window_create_flags(yctx, width + bounds.width, height + bounds.height, YUTANI_WINDOW_FLAG_DIALOG_ANIMATION);
	req_center_x = yctx->display_width / 2;
	req_center_y = yctx->display_height / 2;

	if (argc < 2) {
		init_default();
	} else if (argc < 5) {
		fprintf(stderr, "Invalid arguments.\n");
		return 1;
	} else {
		title_str = argv[1];
		icon_path = argv[2];
		version_str = argv[3];

		int i = 0;
		char * me = argv[4], * end;
		do {
			copyright_str[i] = me;
			i++;
			end = strchr(me,'\n');
			if (end) {
				*end = '\0';
				me = end+1;
			}
		} while (end);

		if (argc > 6) {
			req_center_x = atoi(argv[5]);
			req_center_y = atoi(argv[6]);
		}
	}

	yutani_window_move(yctx, window, req_center_x - window->width / 2, req_center_y - window->height / 2);

	yutani_window_advertise_icon(yctx, window, title_str, "star");

	ctx = init_graphics_yutani_double_buffer(window);
	load_sprite(&logo, icon_path);

	redraw();

	int playing = 1;
	while (playing) {
		yutani_msg_t * m = yutani_poll(yctx);
		while (m) {
			if (menu_process_event(yctx, m)) {
				redraw();
			}
			switch (m->type) {
				case YUTANI_MSG_KEY_EVENT:
					{
						struct yutani_msg_key_event * ke = (void*)m->data;
						if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
							playing = 0;
						}
					}
					break;
				case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
					{
						struct yutani_msg_window_focus_change * wf = (void*)m->data;
						yutani_window_t * win = hashmap_get(yctx->windows, (void*)(uintptr_t)wf->wid);
						if (win) {
							win->focused = wf->focused;
							redraw();
						}
					}
					break;
				case YUTANI_MSG_RESIZE_OFFER:
					{
						struct yutani_msg_window_resize * wr = (void*)m->data;
						resize_finish(wr->width, wr->height);
					}
					break;
				case YUTANI_MSG_WINDOW_MOUSE_EVENT:
					{
						struct yutani_msg_window_mouse_event * me = (void*)m->data;
						int result = decor_handle_event(yctx, m);
						switch (result) {
							case DECOR_CLOSE:
								playing = 0;
								break;
							case DECOR_RIGHT:
								/* right click in decoration, show appropriate menu */
								decor_show_default_menu(window, window->x + me->new_x, window->y + me->new_y);
								break;
							default:
								/* Other actions */
								break;
						}
					}
					break;
				case YUTANI_MSG_WINDOW_CLOSE:
				case YUTANI_MSG_SESSION_END:
					playing = 0;
					break;
				default:
					break;
			}
			free(m);
			m = yutani_poll_async(yctx);
		}
	}

	yutani_close(yctx, window);

	return 0;
}


================================================
FILE: apps/basename.c
================================================
/**
 * @brief basename - print file name
 *
 * @copyright
 * This file is part of ToaruOS and is released under the terms
 * of the NCSA / University of Illinois License - see LICENSE.md
 * Copyright (C) 2018 K. Lange
 */
#include <stdio.h>
#include <string.h>
#include <libgen.h>

int main(int argc, char * argv[]) {
	if (argc < 2) {
		fprintf(stderr, "%s: expected argument\n", argv[0]);
		return 1;
	}

	char * c = basename(argv[1]);

	if (argc > 2) {
		char * suffix = argv[2];
		char * found = strstr(c + strlen(c) - strlen(suffix), suffix);
		if (found && (found - c == (int)(strlen(c)-strlen(suffix)))) {
			*found = '\0';
		}
	}

	fprintf(stdout, "%s\n", c);
	return 0;
}


================================================
FILE: apps/beep.c
================================================
/**
 * @brief Implementation of the 'beep' utility.
 *
 * I've tried to get the functionality here as close to the common
 * utility available on Linux systems so that "beep music" can be
 * played back.
 *
 * @copyright
 * This file is part of ToaruOS and is released under the terms
 * of the NCSA / University of Illinois License - see LICENSE.md
 * Copyright (C) 2014-2018 K. Lange
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int spkr = 0;

struct spkr {
	int length;
	int frequency;
};

static void note(int length, int frequency) {
	struct spkr s = {
		.length = length,
		.frequency = frequency,
	};

	write(spkr, &s, sizeof(s));
}

/* Stolen from the Linux tool */
#define DEFAULT_FREQ  440.0
#define DEFAULT_LEN   200
#define DEFAULT_DELAY 100

static int repetitions = 1;
static float frequency = DEFAULT_FREQ;
static int length      = DEFAULT_LEN;
static int delay       = DEFAULT_DELAY;
static int beep_after  = 0;

void beep(void) {
	for (int i = 0; i < repetitions; ++i) {
		note(length, frequency * 10);
		if (delay && ((i != repetitions - 1) || beep_after)) {
			usleep(delay * 1000);
		}
	}

}

int main(int argc, char * argv[]) {

	spkr = open("/dev/spkr", O_WRONLY);
	if (spkr == -1) {
		fprintf(stderr, "%s: could not open speaker\n", argv[0]);
	}

	int opt;
	while ((opt = getopt(argc, argv, "?hr:f:l:d:D:n")) != -1) {
		switch (opt) {
			case 'h':
			case '?':
				fprintf(stderr, "usage: %s BEEP...\n"
						"Where BEEP consists of:\n"
						"  -r  REPS  \033[3mNumber of repetitions.\033[0m\n"
						"  -f  FREQ  \033[3mFrequency in Hz. 440 is A4. Supports fractional values.\033[0m\n"
						"  -l  TIME  \033[3mDuration in milliseconds.\033[0m\n"
						"  -d  TIME  \033[3mDelay between repetitions in milliseconds.\033[0m\n"
						"  -D  TIME  \033[3mDelay between, and after, repetitions.\033[0m\n"
						"  -n        \033[3mStart a new beep.\033[0m\n"
						"\n"
						"The default values are:\n"
						"   -r 1 -l %d -f %.2f -d %d\n"
						"\n"
						"A length of -1 will start a sustained beep without blocking.\n"
						"A length of 0 will stop a currently playing sustained beep.\n",
						argv[0], DEFAULT_LEN, DEFAULT_FREQ, DEFAULT_DELAY);
				return 1;
			case 'r':
				repetitions = atoi(optarg);
				break;
			case 'l':
				length = atoi(optarg);
				break;
			case 'f':
				frequency = atof(optarg);
				break;
			case 'd':
				delay = atoi(optarg);
				beep_after = 0;
				break;
			case 'D':
				delay = atoi(optarg);
				beep_after = 1;
				break;
			case 'n':
				beep();
				repetitions = 1;
				frequency = DEFAULT_FREQ;
				length = DEFAULT_LEN;
				delay = DEFAULT_DELAY;
				beep_after = 0;
				break;
		}
	}

	beep();

	return 0;
}



================================================
FILE: apps/bim.c
================================================
/* Bim - A Text Editor
 *
 * Copyright (C) 2012-2026 K. Lange
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "bim.h"

#define BIM_VERSION   "3.2.0" TAG
#define BIM_COPYRIGHT "Copyright 2012-2026 K. Lange <\033[3mklange@toaruos.org\033[23m>"

#include <kuroko/kuroko.h>
#include <kuroko/vm.h>
#include <kuroko/debug.h>
#include <kuroko/util.h>
#include <kuroko/scanner.h>

global_config_t global_config = {
	/* State */
	.term_width = 0,
	.term_height = 0,
	.bottom_size = 2,
	.yanks = NULL,
	.yank_count = 0,
	.yank_is_full_lines = 0,
	.tty_in = STDIN_FILENO,
	.bimrc_path = "~/.bim3rc",
	.syntax_fallback = NULL, /* Syntax to fall back to if no other match applies */
	.search = NULL,
	.overlay_mode = OVERLAY_MODE_NONE,
	.command_buffer = NULL,
	.command_offset = 0,
	.command_col_no = 0,
	.history_point = -1,
	.search_point = -1,
	/* Bitset starts here */
	.highlight_on_open = 1,
	.initial_file_is_read_only = 0,
	.go_to_line = 1,
	.break_from_selection = 1,
	/* Terminal capabilities */
	.can_scroll = 1,
	.can_hideshow = 1,
	.can_altscreen = 1,
	.can_mouse = 1,
	.can_unicode = 1,
	.can_bright = 1,
	.can_title = 1,
	.can_bce = 1,
	.can_24bit = 1, /* can use 24-bit color */
	.can_256color = 1, /* can use 265 colors */
	.can_italic = 1, /* can use italics (without inverting) */
	.can_insert = 0, /* ^[[L */
	.can_bracketedpaste = 0, /* puts escapes before and after pasted stuff */
	.can_sgrmouse = 0, /* Whether SGR mouse mode is availabe (large coordinates) */
	/* Configuration options */
	.history_enabled = 1,
	.highlight_parens = 1, /* highlight parens/braces when cursor moves */
	.smart_case = 1, /* smart case-sensitivity while searching */
	.highlight_current_line = 1,
	.shift_scrolling = 1, /* shift rather than moving cursor*/
	.check_git = 0,
	.color_gutter = 1, /* shows modified lines */
	.relative_lines = 0,
	.numbers = 1,
	.horizontal_shift_scrolling = 0, /* Whether to shift the whole screen when scrolling horizontally */
	.hide_statusbar = 0,
	.tabs_visible = 1,
	.autohide_tabs = 0,
	.smart_complete = 0,
	.has_terminal = 0,
	.search_wraps = 1,
	.had_error = 0,
	.use_biminfo = 1,
	/* Integer config values */
	.cursor_padding = 4,
	.split_percent = 50,
	.scroll_amount = 5,
	.tab_offset = 0,
	.background_task = NULL,
	.tail_task = NULL,
	.paren_pairs = NULL,
};

struct key_name_map KeyNames[] = {
	{KEY_TIMEOUT, "[timeout]"},
	{KEY_BACKSPACE, "<backspace>"},
	{KEY_ENTER, "<enter>"},
	{KEY_ESCAPE, "<escape>"},
	{KEY_TAB, "<tab>"},
	{' ', "<space>"},
	/* These are mostly here for markdown output. */
	{'`', "<backtick>"},
	{'|', "<pipe>"},
	{KEY_DELETE, "<del>"},
	{KEY_MOUSE, "<mouse>"},
	{KEY_MOUSE_SGR, "<mouse-sgr>"},
	{KEY_F1, "<f1>"},{KEY_F2, "<f2>"},{KEY_F3, "<f3>"},{KEY_F4, "<f4>"},
	{KEY_F5, "<f5>"},{KEY_F6, "<f6>"},{KEY_F7, "<f7>"},{KEY_F8, "<f8>"},
	{KEY_F9, "<f9>"},{KEY_F10, "<f10>"},{KEY_F11, "<f11>"},{KEY_F12, "<f12>"},
	{KEY_HOME,"<home>"},{KEY_END,"<end>"},{KEY_PAGE_UP,"<page-up>"},{KEY_PAGE_DOWN,"<page-down>"},
	{KEY_UP, "<up>"},{KEY_DOWN, "<down>"},{KEY_RIGHT, "<right>"},{KEY_LEFT, "<left>"},
	{KEY_SHIFT_UP, "<shift-up>"},{KEY_SHIFT_DOWN, "<shift-down>"},{KEY_SHIFT_RIGHT, "<shift-right>"},{KEY_SHIFT_LEFT, "<shift-left>"},
	{KEY_CTRL_UP, "<ctrl-up>"},{KEY_CTRL_DOWN, "<ctrl-down>"},{KEY_CTRL_RIGHT, "<ctrl-right>"},{KEY_CTRL_LEFT, "<ctrl-left>"},
	{KEY_ALT_UP, "<alt-up>"},{KEY_ALT_DOWN, "<alt-down>"},{KEY_ALT_RIGHT, "<alt-right>"},{KEY_ALT_LEFT, "<alt-left>"},
	{KEY_ALT_SHIFT_UP, "<alt-shift-up>"},{KEY_ALT_SHIFT_DOWN, "<alt-shift-down>"},{KEY_ALT_SHIFT_RIGHT, "<alt-shift-right>"},{KEY_ALT_SHIFT_LEFT, "<alt-shift-left>"},
	{KEY_SHIFT_TAB,"<shift-tab>"},
	{KEY_PASTE_BEGIN,"<paste-begin>"},{KEY_PASTE_END,"<paste-end>"},
};

char * name_from_key(enum Key keycode) {
	for (unsigned int i = 0;  i < sizeof(KeyNames)/sizeof(KeyNames[0]); ++i) {
		if (KeyNames[i].keycode == keycode) return KeyNames[i].name;
	}
	static char keyNameTmp[8] = {0};
	if (keycode <= KEY_CTRL_UNDERSCORE) {
		keyNameTmp[0] = '^';
		keyNameTmp[1] = '@' + keycode;
		keyNameTmp[2] = 0;
		return keyNameTmp;
	}
	to_eight(keycode, keyNameTmp);
	return keyNameTmp;
}

#define S(c) (krk_copyString(c,sizeof(c)-1))

#define CURRENT_NAME self
static KrkClass * syntaxStateClass = NULL;

struct SyntaxState {
	KrkInstance inst;
	struct syntax_state state;
};

static void schedule_complete_recalc(void);

/**
 * Theming data
 *
 * This default set is pretty simple "default foreground on default background"
 * except for search and selections which are black-on-white specifically.
 *
 * The theme colors get set by separate configurable theme scripts.
 */
const char * COLOR_FG        = "@9";
const char * COLOR_BG        = "@9";
const char * COLOR_ALT_FG    = "@9";
const char * COLOR_ALT_BG    = "@9";
const char * COLOR_NUMBER_FG = "@9";
const char * COLOR_NUMBER_BG = "@9";
const char * COLOR_STATUS_FG = "@9";
const char * COLOR_STATUS_BG = "@9";
const char * COLOR_STATUS_ALT= "@9";
const char * COLOR_TABBAR_BG = "@9";
const char * COLOR_TAB_BG    = "@9";
const char * COLOR_ERROR_FG  = "@9";
const char * COLOR_ERROR_BG  = "@9";
const char * COLOR_SEARCH_FG = "@0";
const char * COLOR_SEARCH_BG = "@17";
const char * COLOR_KEYWORD   = "@9";
const char * COLOR_STRING    = "@9";
const char * COLOR_COMMENT   = "@9";
const char * COLOR_TYPE      = "@9";
const char * COLOR_PRAGMA    = "@9";
const char * COLOR_NUMERAL   = "@9";
const char * COLOR_SELECTFG  = "@0";
const char * COLOR_SELECTBG  = "@17";
const char * COLOR_RED       = "@1";
const char * COLOR_GREEN     = "@2";
const char * COLOR_BOLD      = "@9";
const char * COLOR_LINK      = "@9";
const char * COLOR_ESCAPE    = "@9";
const char * current_theme = "none";

struct ColorName color_names[] = {
	{"text-fg", &COLOR_FG},
	{"text-bg", &COLOR_BG},
	{"alternate-fg", &COLOR_ALT_FG},
	{"alternate-bg", &COLOR_ALT_BG},
	{"number-fg", &COLOR_NUMBER_FG},
	{"number-bg", &COLOR_NUMBER_BG},
	{"status-fg", &COLOR_STATUS_FG},
	{"status-bg", &COLOR_STATUS_BG},
	{"status-alt", &COLOR_STATUS_ALT},
	{"tabbar-bg", &COLOR_TABBAR_BG},
	{"tab-bg", &COLOR_TAB_BG},
	{"error-fg", &COLOR_ERROR_FG},
	{"error-bg", &COLOR_ERROR_BG},
	{"search-fg", &COLOR_SEARCH_FG},
	{"search-bg", &COLOR_SEARCH_BG},
	{"keyword", &COLOR_KEYWORD},
	{"string", &COLOR_STRING},
	{"comment", &COLOR_COMMENT},
	{"type", &COLOR_TYPE},
	{"pragma", &COLOR_PRAGMA},
	{"numeral", &COLOR_NUMERAL},
	{"select-fg", &COLOR_SELECTFG},
	{"select-bg", &COLOR_SELECTBG},
	{"red", &COLOR_RED},
	{"green", &COLOR_GREEN},
	{"bold", &COLOR_BOLD},
	{"link", &COLOR_LINK},
	{"escape", &COLOR_ESCAPE},
	{NULL,NULL},
};


#define FLEXIBLE_ARRAY(name, add_name, type, zero) \
	int flex_ ## name ## _count = 0; \
	int flex_ ## name ## _space = 0; \
	type * name = NULL; \
	void add_name (type input) { \
		if (flex_ ## name ## _space == 0) { \
			flex_ ## name ## _space = 4; \
			name = calloc(sizeof(type), flex_ ## name ## _space); \
		} else if (flex_ ## name ## _count + 1 == flex_ ## name ## _space) { \
			flex_ ## name ## _space *= 2; \
			name = realloc(name, sizeof(type) * flex_ ## name ## _space); \
			for (int i = flex_ ## name ## _count; i < flex_ ## name ## _space; ++i) name[i] = zero; \
		} \
		name[flex_ ## name ## _count] = input; \
		flex_ ## name ## _count ++; \
	}

FLEXIBLE_ARRAY(mappable_actions, add_action, struct action_def, ((struct action_def){NULL,0,0,NULL}))
FLEXIBLE_ARRAY(regular_commands, add_command, struct command_def, ((struct command_def){NULL,NULL,NULL}))
FLEXIBLE_ARRAY(prefix_commands, add_prefix_command, struct command_def, ((struct command_def){NULL,NULL,NULL}))
FLEXIBLE_ARRAY(themes, add_colorscheme, struct theme_def, ((struct theme_def){NULL,NULL}))

/**
 * Special implementation of getch with a timeout
 */
int _bim_unget = -1;

void bim_unget(int c) {
	_bim_unget = c;
}

void redraw_statusbar(void);
int bim_getch_timeout(int timeout) {
	fflush(stdout);
	if (_bim_unget != -1) {
		int out = _bim_unget;
		_bim_unget = -1;
		return out;
	}
	struct pollfd fds[1];
	fds[0].fd = global_config.tty_in;
	fds[0].events = POLLIN;
	int ret = poll(fds,1,timeout);
	if (ret > 0 && fds[0].revents & POLLIN) {
		unsigned char buf[1];
		read(global_config.tty_in, buf, 1);
		return buf[0];
	} else {
		background_task_t * task = global_config.background_task;
		if (task) {
			global_config.background_task = task->next;
			task->func(task);
			free(task);
			if (!global_config.background_task) {
				global_config.tail_task = NULL;
				redraw_statusbar();
			}
		}
		return -1;
	}
}

/**
 * UTF-8 parser state
 *
 * TODO Why is this state global? Should be per-buffer or otherwise managed by add_buffer, and probably
 *      reset a lot more often than we are currently resetting it.
 */
static uint32_t codepoint_r;
static uint32_t state = 0;

#define UTF8_ACCEPT 0
#define UTF8_REJECT 1

static inline uint32_t decode(uint32_t* state, uint32_t* codep, unsigned char byte) {
	static int state_table[32] = {
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xxxxxxx */
		1,1,1,1,1,1,1,1,                 /* 10xxxxxx */
		2,2,2,2,                         /* 110xxxxx */
		3,3,                             /* 1110xxxx */
		4,                               /* 11110xxx */
		1                                /* 11111xxx */
	};

	static int mask_bytes[32] = {
		0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
		0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x1F,0x1F,0x1F,0x1F,
		0x0F,0x0F,
		0x07,
		0x00
	};

	static int next[5] = {
		0,
		1,
		0,
		2,
		3
	};

	if (*state == UTF8_ACCEPT) {
		*codep = byte & mask_bytes[byte >> 3];
		*state = state_table[byte >> 3];
	} else if (*state > 0) {
		*codep = (byte & 0x3F) | (*codep << 6);
		*state = next[*state];
	}
	return *state;
}

#define shift_key(i) _shift_key((i), this_buf, &timeout);
int _shift_key(int i, int this_buf[20], int *timeout) {
	int thing = this_buf[*timeout-1];
	(*timeout) = 0;
	switch (thing) {
		/* There are other combinations we can handle... */
		case '2': return i + 4;
		case '5': return i + 8;
		case '3': return i + 12;
		case '4': return i + 16;
		default: return i;
	}
}

int bim_getkey(int read_timeout) {

	int timeout = 0;
	int this_buf[20];

	int cin;
	uint32_t c;
	uint32_t istate = 0;

	while ((cin = bim_getch_timeout((timeout == 1) ? 50 : read_timeout))) {
		if (cin == -1) {
			if (timeout && this_buf[timeout-1] == '\033')
				return KEY_ESCAPE;
			return KEY_TIMEOUT;
		}

		if (!decode(&istate, &c, cin)) {
			if (timeout == 0) {
				switch (c) {
					case '\033':
						if (timeout == 0) {
							this_buf[timeout] = c;
							timeout++;
						}
						continue;
					case KEY_LINEFEED: return KEY_ENTER;
					case KEY_DELETE: return KEY_BACKSPACE;
				}
				return c;
			} else {
				if (timeout >= 1 && this_buf[timeout-1] == '\033' && c == '\033') {
					bim_unget(c);
					timeout = 0;
					return KEY_ESCAPE;
				}
				if (timeout >= 1 && this_buf[0] == '\033' && c == 'O') {
					this_buf[timeout] = c;
					timeout++;
					continue;
				}
				if (timeout >= 2 && this_buf[0] == '\033' && this_buf[1] == 'O') {
					switch (c) {
						case 'P': return KEY_F1;
						case 'Q': return KEY_F2;
						case 'R': return KEY_F3;
						case 'S': return KEY_F4;
					}
					timeout = 0;
					continue;
				}
				if (timeout >= 1 && this_buf[timeout-1] == '\033' && c != '[') {
					timeout = 0;
					bim_unget(c);
					return KEY_ESCAPE;
				}
				if (timeout >= 1 && this_buf[timeout-1] == '\033' && c == '[') {
					timeout = 1;
					this_buf[timeout] = c;
					timeout++;
					continue;
				}
				if (timeout >= 2 && this_buf[0] == '\033' && this_buf[1] == '[' &&
				    (isdigit(c) || (c == ';'))) {
					this_buf[timeout] = c;
					timeout++;
					continue;
				}
				if (timeout >= 2 && this_buf[0] == '\033' && this_buf[1] == '[') {
					switch (c) {
						case 'M': return KEY_MOUSE;
						case '<': return KEY_MOUSE_SGR;
						case 'A': return shift_key(KEY_UP);
						case 'B': return shift_key(KEY_DOWN);
						case 'C': return shift_key(KEY_RIGHT);
						case 'D': return shift_key(KEY_LEFT);
						case 'H': return KEY_HOME;
						case 'F': return KEY_END;
						case 'I': return KEY_PAGE_UP;
						case 'G': return KEY_PAGE_DOWN;
						case 'Z': return KEY_SHIFT_TAB;
						case '~':
							if (timeout == 3) {
								switch (this_buf[2]) {
									case '1': return KEY_HOME;
									case '3': return KEY_DELETE;
									case '4': return KEY_END;
									case '5': return KEY_PAGE_UP;
									case '6': return KEY_PAGE_DOWN;
								}
							} else if (timeout == 5) {
								if (this_buf[2] == '2' && this_buf[3] == '0' && this_buf[4] == '0') {
									return KEY_PASTE_BEGIN;
								} else if (this_buf[2] == '2' && this_buf[3] == '0' && this_buf[4] == '1') {
									return KEY_PASTE_END;
								}
							} else if (this_buf[2] == '1') {
								switch (this_buf[3]) {
									case '5': return KEY_F5;
									case '7': return KEY_F6;
									case '8': return KEY_F7;
									case '9': return KEY_F8;
								}
							} else if (this_buf[2] == '2') {
								switch (this_buf[3]) {
									case '0': return KEY_F9;
									case '1': return KEY_F10;
									case '3': return KEY_F11;
									case '4': return KEY_F12;
								}
							}
							break;
					}
				}
				timeout = 0;
				continue;
			}
		} else if (istate == UTF8_REJECT) {
			istate = 0;
		}
	}

	return KEY_TIMEOUT;
}

enum Key key_from_name(const char * name) {
	for (unsigned int i = 0;  i < sizeof(KeyNames)/sizeof(KeyNames[0]); ++i) {
		if (!strcmp(KeyNames[i].name, name)) return KeyNames[i].keycode;
	}
	if (name[0] == '^' && name[1] && !name[2]) {
		return name[1] - '@';
	}
	if (!name[1]) return name[0];
	/* Try decoding */
	uint32_t c, state = 0;
	int candidate = -1;
	while (*name) {
		if (!decode(&state, &c, (unsigned char)*name)) {
			if (candidate == -1) candidate = c;
			else return -1; /* Reject `name` if it is multiple codepoints */
		} else if (state == UTF8_REJECT) {
			return -1;
		}
	}
	return candidate;
}


/**
 * Pointer to current active buffer
 */
buffer_t * env = NULL;

buffer_t * left_buffer = NULL;
buffer_t * right_buffer = NULL;

/**
 * A buffer for holding a number (line, repetition count)
 */
#define NAV_BUFFER_MAX 10
char nav_buf[NAV_BUFFER_MAX+1];
int nav_buffer = 0;

/**
 * Available buffers
 */
int    buffers_len = 0;
int    buffers_avail = 0;
buffer_t ** buffers = NULL;

/**
 * Create a new buffer
 */
buffer_t * buffer_new(void) {
	if (buffers_len == buffers_avail) {
		/* If we are out of buffer space, expand the buffers vector */
		buffers_avail *= 2;
		buffers = realloc(buffers, sizeof(buffer_t *) * buffers_avail);
	}

	/* TODO: Clean up split support and support multiple splits... */
	if (left_buffer) {
		left_buffer->left = 0;
		left_buffer->width = global_config.term_width;
		right_buffer->left = 0;
		right_buffer->width = global_config.term_width;
		left_buffer = NULL;
		right_buffer = NULL;
	}

	/* Allocate a new buffer */
	buffers[buffers_len] = malloc(sizeof(buffer_t));
	memset(buffers[buffers_len], 0x00, sizeof(buffer_t));
	buffers[buffers_len]->left = 0;
	buffers[buffers_len]->width = global_config.term_width;
	buffers[buffers_len]->highlighting_paren = -1;
	buffers[buffers_len]->numbers = global_config.numbers;
	buffers[buffers_len]->gutter = 1;
	buffers_len++;
	global_config.tabs_visible = (!global_config.autohide_tabs) || (buffers_len > 1);

	return buffers[buffers_len-1];
}

/**
 * Open the biminfo file.
 */
FILE * open_biminfo(void) {
	if (!global_config.use_biminfo) return NULL;

	char * home = getenv("HOME");
	if (!home) {
		/* ... but since it's not, we need $HOME, so fail if it isn't set. */
		return NULL;
	}

	/* biminfo lives at ~/.biminfo */
	char biminfo_path[PATH_MAX+1] = {0};
	sprintf(biminfo_path,"%s/.biminfo",home);

	/* Try to open normally first... */
	FILE * biminfo = fopen(biminfo_path,"r+");
	if (!biminfo) {
		/* Otherwise, try to create it. */
		biminfo = fopen(biminfo_path,"w+");
	}
	return biminfo;
}

/**
 * Check if a file is open by examining the biminfo file
 */
int file_is_open(char * file) {
	/* Get the absolute path of the file to normalize for lookup */
	char * _file = file;
	if (file[0] == '~') {
		char * home = getenv("HOME");
		if (home) {
			_file = malloc(strlen(file) + strlen(home) + 4); /* Paranoia */
			sprintf(_file, "%s%s", home, file+1);
		}
	}

	char tmp_path[PATH_MAX+2];
	if (!realpath(_file, tmp_path)) {
		if (_file != file) free(_file);
		return 0; /* Assume not */
	}
	if (_file != file) free(_file);
	strcat(tmp_path," ");

	FILE * biminfo = open_biminfo();
	if (!biminfo) return 0; /* Assume not */

	/* Scan */
	char line[PATH_MAX+64];

	while (!feof(biminfo)) {
		fpos_t start_of_line;
		fgetpos(biminfo, &start_of_line);
		fgets(line, PATH_MAX+63, biminfo);
		if (line[0] != '%') {
			continue;
		}

		if (!strncmp(&line[1],tmp_path, strlen(tmp_path))) {
			/* File is currently open */
			int pid = -1;
			sscanf(line+1+strlen(tmp_path)+1,"%d",&pid);
			if (pid != -1 && pid != getpid()) {
				if (!kill(pid, 0)) {
					int key = 0;
					render_error("biminfo indicates another instance may already be editing this file");
					render_commandline_message("\n");
					render_commandline_message("file path = %s\n", tmp_path);
					render_commandline_message("pid = %d (still running)\n", pid);
					render_commandline_message("Open file anyway? (y/N)");
					while ((key = bim_getkey(DEFAULT_KEY_WAIT)) == KEY_TIMEOUT);
					if (key != 'y') {
						fclose(biminfo);
						return 1;
					}
				}
			}
			fclose(biminfo);
			return 0;
		}
	}
	fclose(biminfo);
	return 0;
}

/**
 * Fetch the cursor position from a biminfo file
 */
int fetch_from_biminfo(buffer_t * buf) {
	/* Can't fetch if we don't have a filename */
	if (!buf->file_name) return 1;

	char * file = buf->file_name;
	char * _file = file;
	if (file[0] == '~') {
		char * home = getenv("HOME");
		if (home) {
			_file = malloc(strlen(file) + strlen(home) + 4); /* Paranoia */
			sprintf(_file, "%s%s", home, file+1);
		}
	}

	/* Get the absolute path of the file to normalize for lookup */
	char tmp_path[PATH_MAX+2];
	if (!realpath(_file, tmp_path)) {
		if (_file != file) free(_file);
		return 1;
	}
	if (_file != file) free(_file);
	strcat(tmp_path," ");

	FILE * biminfo = open_biminfo();
	if (!biminfo) return 1;

	/* Scan */
	char line[PATH_MAX+64];

	while (!feof(biminfo)) {
		fpos_t start_of_line;
		fgetpos(biminfo, &start_of_line);
		fgets(line, PATH_MAX+63, biminfo);
		if (line[0] != '>') {
			continue;
		}

		if (!strncmp(&line[1],tmp_path, strlen(tmp_path))) {
			/* Read */
			sscanf(line+1+strlen(tmp_path)+1,"%d",&buf->line_no);
			sscanf(line+1+strlen(tmp_path)+21,"%d",&buf->col_no);

			if (buf->line_no > buf->line_count) buf->line_no = buf->line_count;
			if (buf->col_no > buf->lines[buf->line_no-1]->actual) buf->col_no = buf->lines[buf->line_no-1]->actual;
			try_to_center();

			fclose(biminfo);
			return 0;
		}
	}

	fclose(biminfo);
	return 0;
}

/**
 * Write a file containing the last cursor position of a buffer.
 */
int update_biminfo(buffer_t * buf, int is_open) {
	if (!buf->file_name) return 1;

	char * file = buf->file_name;
	char * _file = file;
	if (file[0] == '~') {
		char * home = getenv("HOME");
		if (home) {
			_file = malloc(strlen(file) + strlen(home) + 4); /* Paranoia */
			sprintf(_file, "%s%s", home, file+1);
		}
	}

	/* Get the absolute path of the file to normalize for lookup */
	char tmp_path[PATH_MAX+1];
	if (!realpath(_file, tmp_path)) {
		if (_file != file) free(_file);
		return 1;
	}
	if (_file != file) free(_file);
	strcat(tmp_path," ");

	FILE * biminfo = open_biminfo();
	if (!biminfo) return 1;

	/* Scan */
	char line[PATH_MAX+64];

	while (!feof(biminfo)) {
		fpos_t start_of_line;
		fgetpos(biminfo, &start_of_line);
		fgets(line, PATH_MAX+63, biminfo);
		if (line[0] != '>' && line[0] != '%') {
			continue;
		}

		if (!strncmp(&line[1],tmp_path, strlen(tmp_path))) {
			/* Update */
			fsetpos(biminfo, &start_of_line);
			fprintf(biminfo,"%c%s %20d %20d\n", is_open ? '%' : '>', tmp_path,
				is_open ? getpid() : buf->line_no, buf->col_no);
			goto _done;
		}
	}

	if (ftell(biminfo) == 0) {
		/* New biminfo */
		fprintf(biminfo, "# This is a biminfo file.\n");
		fprintf(biminfo, "# It was generated by bim. Do not edit it by hand!\n");
		fprintf(biminfo, "# Cursor positions and other state are stored here.\n");
	}

	/* If we reach this point, we didn't find a record for this file
	 * and the write cursor should be at the end, so just add a new line */
	fprintf(biminfo,"%c%s %20d %20d\n", is_open ? '%' : '>', tmp_path,
		is_open ? getpid() : buf->line_no, buf->col_no);

_done:
	fclose(biminfo);
	return 0;
}

void cancel_background_tasks(buffer_t * buf) {
	background_task_t * t = global_config.background_task;
	background_task_t * last = NULL;
	while (t) {
		if (t->env == buf) {
			if (last) {
				last->next = t->next;
			} else {
				global_config.background_task = t->next;
			}
			if (!t->next) {
				global_config.tail_task = last;
			}
			background_task_t * tmp = t->next;
			free(t);
			t = tmp;
		} else {
			last = t;
			t = t->next;
		}
	}
}

/**
 * Close a buffer
 */
buffer_t * buffer_close(buffer_t * buf) {
	int i;

	/* Locate the buffer in the buffer list */
	for (i = 0; i < buffers_len; i++) {
		if (buf == buffers[i])
			break;
	}

	/* This buffer doesn't exist? */
	if (i == buffers_len) {
		return NULL;
	}

	/* Cancel any background tasks for this env */
	cancel_background_tasks(buf);

	update_biminfo(buf, 0);

	/* Clean up lines used by old buffer */
	for (int i = 0; i < buf->line_count; ++i) {
		free(buf->lines[i]);
	}

	free(buf->lines);

	if (buf->file_name) {
		free(buf->file_name);
	}

	history_t * h = buf->history;
	while (h->next) {
		h = h->next;
	}
	while (h) {
		history_t * x = h->previous;
		free(h);
		h = x;
	}

	/* Clean up the old buffer */
	free(buf);

	/* Remove the buffer from the vector, moving others up */
	if (i != buffers_len - 1) {
		memmove(&buffers[i], &buffers[i+1], sizeof(*buffers) * (buffers_len - i - 1));
	}

	/* There is one less buffer */
	buffers_len--;
	if (buffers_len && global_config.tab_offset >= buffers_len) global_config.tab_offset--;
	global_config.tabs_visible = (!global_config.autohide_tabs) || (buffers_len > 1);
	if (!buffers_len) { 
		/* There are no more buffers. */
		return NULL;
	}

	/* If this was the last buffer in the list, return the previous last buffer */
	if (i == buffers_len) {
		return buffers[buffers_len-1];
	}

	/* Otherwise return the buffer in the same location */
	return buffers[i];
}

/**
 * Convert syntax highlighting flag to color code
 */
const char * flag_to_color(int _flag) {
	int flag = _flag & FLAG_MASK_COLORS;
	switch (flag) {
		case FLAG_KEYWORD:
			return COLOR_KEYWORD;
		case FLAG_STRING:
			return COLOR_STRING;
		case FLAG_COMMENT:
			return COLOR_COMMENT;
		case FLAG_TYPE:
			return COLOR_TYPE;
		case FLAG_NUMERAL:
			return COLOR_NUMERAL;
		case FLAG_PRAGMA:
			return COLOR_PRAGMA;
		case FLAG_DIFFPLUS:
			return COLOR_GREEN;
		case FLAG_DIFFMINUS:
			return COLOR_RED;
		case FLAG_SELECT:
			return COLOR_FG;
		case FLAG_BOLD:
			return COLOR_BOLD;
		case FLAG_LINK_COLOR:
			return COLOR_LINK;
		case FLAG_ESCAPE:
			return COLOR_ESCAPE;
		default:
			return COLOR_FG;
	}
}

/**
 * Match and paint a single keyword. Returns 1 if the keyword was matched and 0 otherwise,
 * so it can be used for prefix checking for things that need further special handling.
 */
static int match_and_paint(struct syntax_state * state, const char * keyword, int flag, int (*keyword_qualifier)(int c)) {
	if (keyword_qualifier(lastchar())) return 0;
	if (!keyword_qualifier(charat())) return 0;
	int i = state->i;
	int slen = 0;
	while (i < state->line->actual || *keyword == '\0') {
		if (*keyword == '\0' && (i >= state->line->actual || !keyword_qualifier(state->line->text[i].codepoint))) {
			for (int j = 0; j < slen; ++j) {
				paint(1, flag);
			}
			return 1;
		}
		if (*keyword != state->line->text[i].codepoint) return 0;

		i++;
		keyword++;
		slen++;
	}
	return 0;
}

/**
 * This is a basic character matcher for "keyword" characters.
 */
static int simple_keyword_qualifier(int c) {
	return isalnum(c) || (c == '_');
}

/**
 * These words can appear in comments and should be highlighted.
 * Since there are a lot of comment highlighters, this is provided
 * as a common function that can be used by multiple highlighters.
 */
static int common_comment_buzzwords(struct syntax_state * state) {
	if (match_and_paint(state, "TODO", FLAG_NOTICE, simple_keyword_qualifier)) { return 1; }
	else if (match_and_paint(state, "XXX", FLAG_NOTICE, simple_keyword_qualifier)) { return 1; }
	else if (match_and_paint(state, "FIXME", FLAG_ERROR, simple_keyword_qualifier)) { return 1; }
	return 0;
}

/**
 * Paint a comment until end of line; assumes this comment can not continue.
 * (Some languages have comments that can continue with a \ - don't use this!)
 * Assumes you've already painted your comment start characters.
 */
static int paint_comment(struct syntax_state * state) {
	while (charat() != -1) {
		if (common_comment_buzzwords(state)) continue;
		else { paint(1, FLAG_COMMENT); }
	}
	return -1;
}

/**
 * Find and return a highlighter by name, or return NULL if none was found.
 */
static struct syntax_definition * find_syntax_calculator(const char * name) {
	for (struct syntax_definition * s = syntaxes; syntaxes && s->name; ++s) {
		if (!strcmp(s->name, name)) {
			return s;
		}
	}
	return NULL;
}

int syntax_count = 0;
int syntax_space = 0;
struct syntax_definition * syntaxes = NULL;

void add_syntax(struct syntax_definition def) {
	/* See if a name match already exists for this def. */
	for (struct syntax_definition * s = syntaxes; syntaxes && s->name; ++s) {
		if (!strcmp(def.name,s->name)) {
			*s = def;
			return;
		}
	}

	if (syntax_space == 0) {
		syntax_space = 4;
		syntaxes = calloc(sizeof(struct syntax_definition), syntax_space);
	} else if (syntax_count +1 == syntax_space) {
		syntax_space *= 2;
		syntaxes = realloc(syntaxes, sizeof(struct syntax_definition) * syntax_space);
		for (int i = syntax_count; i < syntax_space; ++i) syntaxes[i].name = NULL;
	}
	syntaxes[syntax_count] = def;
	syntax_count++;
}

void redraw_all(void);

/**
 * Calculate syntax highlighting for the given line, and lines after
 * if their initial syntax state has changed by this recalculation.
 *
 * If `line_no` is -1, this line is taken to be a special line and not
 * part of a buffer; search highlighting will not be processed and syntax
 * highlighting will halt after the line is finished.
 *
 * If `env->slowop` is currently enabled, recalculation is skipped.
 */
void recalculate_syntax(line_t * line, int line_no) {
	if (env->slowop) return;
	/* Clear syntax for this line first */
	int is_original = 1;
	while (1) {
		for (int i = 0; i < line->actual; ++i) {
			line->text[i].flags = line->text[i].flags & (3 << 5);
		}

		if (!env->syntax) {
			if (line_no != -1) rehighlight_search(line);
			return;
		}

		/* Start from the line's stored in initial state */
		struct SyntaxState * s = (void*)krk_newInstance(env->syntax->krkClass);
		s->state.env = env;
		s->state.line = line;
		s->state.line_no = line_no;
		s->state.state = line->istate;
		s->state.i = 0;

		while (1) {
			struct termios old, new;
			tcgetattr(global_config.tty_in, &old);
			new = old; new.c_lflag |= ISIG;
			tcsetattr(global_config.tty_in, TCSANOW, &new);
			ptrdiff_t before = krk_currentThread.stackTop - krk_currentThread.stack;
			krk_push(OBJECT_VAL(env->syntax->krkFunc));
			krk_push(OBJECT_VAL(s));
			KrkValue result = krk_callStack(1);
			tcsetattr(global_config.tty_in, TCSANOW, &old);
			krk_currentThread.stackTop = krk_currentThread.stack + before;
			if (IS_NONE(result) && (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
				render_error("Exception occurred in plugin: %s", AS_INSTANCE(krk_currentThread.currentException)->_class->name->chars);
				render_commandline_message("\n");
				krk_dumpTraceback();
				goto _syntaxError;
			} else if (!IS_NONE(result) && !IS_INTEGER(result)) {
				render_error("Instead of an integer, got %s", krk_typeName(result));
				render_commandline_message("\n");
				goto _syntaxError;
			}
			s->state.state = IS_NONE(result) ? -1 : AS_INTEGER(result);

			if (s->state.state != 0) {
				if (line_no == -1) return;
				rehighlight_search(line);
				if (!is_original) {
					redraw_line(line_no);
				}
				if (line_no + 1 < env->line_count && env->lines[line_no+1]->istate != s->state.state) {
					line_no++;
					line = env->lines[line_no];
					line->istate = s->state.state;
					if (env->loading) return;
					is_original = 0;
					goto _next;
				}
				return;
			}
		}
_next:
		(void)0;
	}

_syntaxError:
	krk_resetStack();
	fprintf(stderr,"This syntax highlighter will be disabled in this environment.");
	env->syntax = NULL;
	cancel_background_tasks(env);
	pause_for_key();
	redraw_all();
}

/**
 * Recalculate tab widths.
 */
void recalculate_tabs(line_t * line) {
	if (env->loading) return;

	int j = 0;
	for (int i = 0; i < line->actual; ++i) {
		if (line->text[i].codepoint == '\t') {
			line->text[i].display_width = env->tabstop - (j % env->tabstop);
		}
		j += line->text[i].display_width;
	}
}

/**
 * The next section contains the basic editing primitives. All other
 * actions are built out of these primitives, and they are the basic
 * instructions that get stored in history to be undone (or redone).
 *
 * Primitives may recalculate syntax or redraw lines, if needed, but only
 * when conditions for redrawing are met (such as not being in `slowop`,
 * or loading the file; also replaying history, or when loading files).
 *
 * At the moment, primitives and most other functions do not take the current
 * buffer (environment) as an argument and instead rely on a global variable;
 * this should definitely be fixed at some point...
 */

/**
 * When a new action that produces history happens and there is forward
 * history that can be redone, we need to erase it as our tree has branched.
 * If we wanted, we could actually story things in a tree structure so that
 * the new branch and the old branch can both stick around, and that should
 * probably be explored in the future...
 */
void history_free(history_t * root) {
	if (!root->next) return;

	/* Find the last entry so we can free backwards */
	history_t * n = root->next;
	while (n->next) {
		n = n->next;
	}

	/* Free everything after the root, including stored content. */
	while (n != root) {
		history_t * p = n->previous;
		switch (n->type) {
			case HISTORY_REPLACE_LINE:
				free(n->contents.remove_replace_line.contents);
				/* fall-through */
			case HISTORY_REMOVE_LINE:
				free(n->contents.remove_replace_line.old_contents);
				break;
			default:
				/* Nothing extra to free */
				break;
		}
		free(n);
		n = p;
	}

	root->next = NULL;
}

/**
 * This macro is called by primitives to insert history elements for each
 * primitive action when performing in edit modes.
 */
#define HIST_APPEND(e) do { \
		e->col = env->col_no; \
		e->line = env->line_no; \
		if (env->history) { \
			e->previous = env->history; \
			history_free(env->history); \
			env->history->next = e; \
			e->next = NULL; \
		} \
		env->history = e; \
	} while (0)

/**
 * Mark a point where a complete set of actions has ended.
 * Individual history entries include things like "insert one character"
 * but a user action that should be undone is "insert several characters";
 * breaks should be inserted after a series of primitives when there is
 * a clear "end", such as when switching out of insert mode after typing.
 */
void set_history_break(void) {
	if (!global_config.history_enabled) return;

	/* Do not produce duplicate breaks, or add breaks if we are at a sentinel. */
	if (env->history->type != HISTORY_BREAK && env->history->type != HISTORY_SENTINEL) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_BREAK;
		HIST_APPEND(e);
	}
}

/**
 * (Primitive) Insert a character into an existing line.
 *
 * This is the most basic primitive action: Take a line, and insert a codepoint
 * into it at a given offset. If `lineno` is not -1, the line is assumed to
 * be part of the active buffer. If inserting a character means the line needs
 * to grow, then it will be reallocated, so the return value of the new line
 * must ALWAYS be used. This primitive will NOT automatically update the
 * buffer with the new pointer, so if you are calling insert on a buffer you
 * MUST update env->lines[lineno-1] yourself.
 */
__attribute__((warn_unused_result)) line_t * line_insert(line_t * line, char_t c, int offset, int lineno) {

	if (!env->loading && global_config.history_enabled && lineno != -1) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_INSERT;
		e->contents.insert_delete_replace.lineno = lineno;
		e->contents.insert_delete_replace.offset = offset;
		e->contents.insert_delete_replace.codepoint = c.codepoint;
		HIST_APPEND(e);
	}

	/* If there is not enough space... */
	if (line->actual == line->available) {
		/* Expand the line buffer */
		if (line->available == 0) {
			line->available = 8;
		} else {
			line->available *= 2;
		}
		line = realloc(line, sizeof(line_t) + sizeof(char_t) * line->available);
	}

	/* If this was not the last character, then shift remaining characters forward. */
	if (offset < line->actual) {
		memmove(&line->text[offset+1], &line->text[offset], sizeof(char_t) * (line->actual - offset));
	}

	/* Insert the new character */
	line->text[offset] = c;

	/* There is one new character in the line */
	line->actual += 1;

	if (!env->loading) {
		line->rev_status = 2; /* Modified */
		recalculate_tabs(line);
		recalculate_syntax(line, lineno);
	}

	return line;
}

/**
 * (Primitive) Delete a character from a line.
 *
 * Remove the character at the given offset. We never shrink lines, so this
 * does not have a return value, and delete should never be called during
 * a loading operation (though it may be called during a history replay).
 */
void line_delete(line_t * line, int offset, int lineno) {

	/* Can't delete character before start of line. */
	if (offset == 0) return;
	/* Can't delete past end of line either */
	if (offset > line->actual) return;

	if (!env->loading && global_config.history_enabled && lineno != -1) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_DELETE;
		e->contents.insert_delete_replace.lineno = lineno;
		e->contents.insert_delete_replace.offset = offset;
		e->contents.insert_delete_replace.old_codepoint = line->text[offset-1].codepoint;
		HIST_APPEND(e);
	}

	/* If this isn't the last character, we need to move all subsequent characters backwards */
	if (offset < line->actual) {
		memmove(&line->text[offset-1], &line->text[offset], sizeof(char_t) * (line->actual - offset));
	}

	/* The line is one character shorter */
	line->actual -= 1;
	line->rev_status = 2;

	recalculate_tabs(line);
	recalculate_syntax(line, lineno);
}

/**
 * (Primitive) Replace a character in a line.
 *
 * Replaces the codepoint at the given offset with a new character. Since this
 * does not involve any size changes, it does not have a return value.
 * Since a replacement character may be a tab, we do still need to recalculate
 * character widths for tabs as they may change.
 */
void line_replace(line_t * line, char_t _c, int offset, int lineno) {

	if (!env->loading && global_config.history_enabled && lineno != -1) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_REPLACE;
		e->contents.insert_delete_replace.lineno = lineno;
		e->contents.insert_delete_replace.offset = offset;
		e->contents.insert_delete_replace.codepoint = _c.codepoint;
		e->contents.insert_delete_replace.old_codepoint = line->text[offset].codepoint;
		HIST_APPEND(e);
	}

	line->text[offset] = _c;

	if (!env->loading) {
		line->rev_status = 2; /* Modified */
		recalculate_tabs(line);
		recalculate_syntax(line, lineno);
	}
}

/**
 * (Primitive) Remove a line from the active buffer
 *
 * This primitive is only valid for a buffer. Delete a line, or if this is the
 * only line in the buffer, clear it but keep the line around with no
 * characters. We use the `line_delete` primitive to clear that line,
 * otherwise we are our own primitive and produce history entries.
 *
 * While we do not shrink the `lines` array, it is returned here anyway.
 */
line_t ** remove_line(line_t ** lines, int offset) {

	/* If there is only one line, clear it instead of removing it. */
	if (env->line_count == 1) {
		while (lines[offset]->actual > 0) {
			line_delete(lines[offset], lines[offset]->actual, offset);
		}
		return lines;
	}

	/* When a line is removed, we need to keep its contents so we
	 * can un-remove it on redo... */
	if (!env->loading && global_config.history_enabled) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_REMOVE_LINE;
		e->contents.remove_replace_line.lineno = offset;
		e->contents.remove_replace_line.old_contents = malloc(sizeof(line_t) + sizeof(char_t) * lines[offset]->available);
		memcpy(e->contents.remove_replace_line.old_contents, lines[offset], sizeof(line_t) + sizeof(char_t) * lines[offset]->available);
		HIST_APPEND(e);
	}

	/* Otherwise, free the data used by the line */
	free(lines[offset]);

	/* Move other lines up */
	if (offset < env->line_count-1) {
		memmove(&lines[offset], &lines[offset+1], sizeof(line_t *) * (env->line_count - (offset - 1)));
		lines[env->line_count-1] = NULL;
	}

	/* There is one less line */
	env->line_count -= 1;
	return lines;
}

/**
 * (Primitive) Add a new line to the active buffer.
 *
 * Inserts a new line into a buffer at the given line offset.
 * Since this grows the buffer, it will return the new line array
 * after reallocation if needed.
 */
line_t ** add_line(line_t ** lines, int offset) {

	/* Invalid offset? */
	if (offset > env->line_count) return lines;

	if (!env->loading && global_config.history_enabled) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_ADD_LINE;
		e->contents.add_merge_split_lines.lineno = offset;
		HIST_APPEND(e);
	}

	/* Not enough space */
	if (env->line_count == env->line_avail) {
		/* Allocate more space */
		env->line_avail *= 2;
		lines = realloc(lines, sizeof(line_t *) * env->line_avail);
	}

	/* If this isn't the last line, move other lines down */
	if (offset < env->line_count) {
		memmove(&lines[offset+1], &lines[offset], sizeof(line_t *) * (env->line_count - offset));
	}

	/* Allocate the new line */
	lines[offset] = calloc(sizeof(line_t) + sizeof(char_t) * 32, 1);
	lines[offset]->available = 32;

	/* There is one new line */
	env->line_count += 1;
	env->lines = lines;

	if (!env->loading) {
		lines[offset]->rev_status = 2; /* Modified */
	}

	if (offset > 0 && !env->loading) {
		recalculate_syntax(lines[offset-1],offset-1);
	}
	return lines;
}

/**
 * (Primitive) Replace a line with data from another line.
 *
 * This is only called when pasting yanks after calling `add_line`,
 * but it allows us to have simpler history for that action.
 */
void replace_line(line_t ** lines, int offset, line_t * replacement) {

	if (!env->loading && global_config.history_enabled) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_REPLACE_LINE;
		e->contents.remove_replace_line.lineno = offset;
		e->contents.remove_replace_line.old_contents = malloc(sizeof(line_t) + sizeof(char_t) * lines[offset]->available);
		memcpy(e->contents.remove_replace_line.old_contents, lines[offset], sizeof(line_t) + sizeof(char_t) * lines[offset]->available);
		e->contents.remove_replace_line.contents = malloc(sizeof(line_t) + sizeof(char_t) * replacement->available);
		memcpy(e->contents.remove_replace_line.contents, replacement, sizeof(line_t) + sizeof(char_t) * replacement->available);
		HIST_APPEND(e);
	}

	if (lines[offset]->available < replacement->actual) {
		lines[offset] = realloc(lines[offset], sizeof(line_t) + sizeof(char_t) * replacement->available);
		lines[offset]->available = replacement->available;
	}
	lines[offset]->actual = replacement->actual;
	memcpy(&lines[offset]->text, &replacement->text, sizeof(char_t) * replacement->actual);

	if (!env->loading) {
		lines[offset]->rev_status = 2;
		recalculate_syntax(lines[offset],offset);
	}
}

/**
 * (Primitive) Merge two consecutive lines.
 *
 * Take two lines in a buffer and turn them into one line.
 * `lineb` is the offset of the second line... or the
 * line number of the first line, depending on which indexing
 * system you prefer to think about. This won't grow `lines`,
 * but it will likely modify it and can reallocate individual
 * lines as well.
 */
line_t ** merge_lines(line_t ** lines, int lineb) {

	/* linea is the line immediately before lineb */
	int linea = lineb - 1;

	if (!env->loading && global_config.history_enabled) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_MERGE_LINES;
		e->contents.add_merge_split_lines.lineno = lineb;
		e->contents.add_merge_split_lines.split = env->lines[linea]->actual;
		HIST_APPEND(e);
	}

	/* If there isn't enough space in linea hold both... */
	if (lines[linea]->available < lines[linea]->actual + lines[lineb]->actual) {
		while (lines[linea]->available < lines[linea]->actual + lines[lineb]->actual) {
			/* ... allocate more space until it fits */
			if (lines[linea]->available == 0) {
				lines[linea]->available = 8;
			} else {
				lines[linea]->available *= 2;
			}
		}
		lines[linea] = realloc(lines[linea], sizeof(line_t) + sizeof(char_t) * lines[linea]->available);
	}

	/* Copy the second line into the first line */
	memcpy(&lines[linea]->text[lines[linea]->actual], &lines[lineb]->text, sizeof(char_t) * lines[lineb]->actual);

	/* The first line is now longer */
	lines[linea]->actual = lines[linea]->actual + lines[lineb]->actual;

	if (!env->loading) {
		lines[linea]->rev_status = 2;
		recalculate_tabs(lines[linea]);
		recalculate_syntax(lines[linea], linea);
	}

	/* Remove the second line */
	free(lines[lineb]);

	/* Move other lines up */
	if (lineb < env->line_count) {
		memmove(&lines[lineb], &lines[lineb+1], sizeof(line_t *) * (env->line_count - (lineb - 1)));
		lines[env->line_count-1] = NULL;
	}

	/* There is one less line */
	env->line_count -= 1;
	return lines;
}

/**
 * (Primitive) Split a line into two lines at the given column.
 *
 * Takes one line and makes it two lines. There are some optimizations
 * if you are trying to "split" at the first or last column, which
 * are both just treated as add_line.
 */
line_t ** split_line(line_t ** lines, int line, int split) {

	/* If we're trying to split from the start, just add a new blank line before */
	if (split == 0) {
		return add_line(lines, line);
	}

	if (!env->loading && global_config.history_enabled) {
		history_t * e = malloc(sizeof(history_t));
		e->type = HISTORY_SPLIT_LINE;
		e->contents.add_merge_split_lines.lineno = line;
		e->contents.add_merge_split_lines.split  = split;
		HIST_APPEND(e);
	}

	if (!env->loading) {
		unhighlight_matching_paren();
	}

	/* Allocate more space as needed */
	if (env->line_count == env->line_avail) {
		env->line_avail *= 2;
		lines = realloc(lines, sizeof(line_t *) * env->line_avail);
	}

	/* Shift later lines down */
	if (line < env->line_count) {
		memmove(&lines[line+2], &lines[line+1], sizeof(line_t *) * (env->line_count - line));
	}

	int remaining = lines[line]->actual - split;

	/* This is some wacky math to get a good power-of-two */
	int v = remaining;
	v--;
	v |= v >> 1;
	v |= v >> 2;
	v |= v >> 4;
	v |= v >> 8;
	v |= v >> 16;
	v++;

	/* Allocate space for the new line */
	lines[line+1] = calloc(sizeof(line_t) + sizeof(char_t) * v, 1);
	lines[line+1]->available = v;
	lines[line+1]->actual = remaining;

	/* Move the data from the old line into the new line */
	memmove(lines[line+1]->text, &lines[line]->text[split], sizeof(char_t) * remaining);
	lines[line]->actual = split;

	if (!env->loading) {
		lines[line]->rev_status = 2;
		lines[line+1]->rev_status = 2;
		recalculate_tabs(lines[line]);
		recalculate_tabs(lines[line+1]);
		recalculate_syntax(lines[line], line);
		recalculate_syntax(lines[line+1], line+1);
	}

	/* There is one new line */
	env->line_count += 1;

	/* We may have reallocated lines */
	return lines;
}

/**
 * Primitives end here. Everything after this point that wants to
 * perform modifications must be built on these primitives and
 * should never directly modify env->lines or the contents thereof,
 * outside of syntax highlighting flag changes.
 */

/**
 * The following section is where we implement "smart" automatic
 * indentation. A lot of this is hacked-together nonsense and "smart"
 * is a bit of an overstatement.
 */

/**
 * Understand spaces and comments and check if the previous line
 * ended with a brace or a colon.
 */
int line_ends_with_brace(line_t * line) {
	int i = line->actual-1;
	while (i >= 0) {
		if ((line->text[i].flags & 0x1F) == FLAG_COMMENT || line->text[i].codepoint == ' ') {
			i--;
		} else {
			break;
		}
	}
	if (i < 0) return 0;
	return (line->text[i].codepoint == '{' || line->text[i].codepoint == ':') ? i+1 : 0;
}

/**
 * Determine if a given line is a comment by checking its initial
 * syntax highlighting state value. This is used by automatic indentation
 * to continue block comments in languages like C.
 *
 * TODO: Why isn't this a syntax-> method?
 */
int line_is_comment(line_t * line) {
	if (!env->syntax) return 0;

	if (!strcmp(env->syntax->name,"c")) {
		if (line->istate == 1) return 1;
	} else if (!strcmp(env->syntax->name,"java")) {
		if (line->istate == 1) return 1;
	} else if (!strcmp(env->syntax->name,"kotlin")) {
		if (line->istate == 1) return 1;
	} else if (!strcmp(env->syntax->name,"rust")) {
		if (line->istate > 0) return 1;
	}

	return 0;
}

/**
 * Figure out where the indentation for a brace belongs by finding
 * where the start of the line is after whitespace. This is called
 * by default when we insert } and tries to align it with the indentation
 * of the matching opening {.
 */
int find_brace_line_start(int line, int col) {
	int ncol = col - 1;
	while (ncol > 0) {
		if (env->lines[line-1]->text[ncol-1].codepoint == ')') {
			int t_line_no = env->line_no;
			int t_col_no = env->col_no;
			env->line_no = line;
			env->col_no = ncol;
			int paren_match_line = -1, paren_match_col = -1;
			find_matching_paren(&paren_match_line, &paren_match_col, 1);

			if (paren_match_line != -1) {
				line = paren_match_line;
			}

			env->line_no = t_line_no;
			env->col_no = t_col_no;
			break;
		} else if (env->lines[line-1]->text[ncol-1].codepoint == ' ') {
			ncol--;
		} else {
			break;
		}
	}
	return line;
}

/**
 * Add indentation from the previous (temporally) line.
 *
 * By "temporally", we mean not necessarily the line above, but
 * potentially the line below if we are inserting a line above
 * the cursor.
 */
void add_indent(int new_line, int old_line, int ignore_brace) {
	if (env->indent) {
		int changed = 0;
		if (old_line < new_line && line_is_comment(env->lines[new_line])) {
			for (int i = 0; i < env->lines[old_line]->actual; ++i) {
				if (env->lines[old_line]->text[i].codepoint == '/') {
					if (env->lines[old_line]->text[i+1].codepoint == '*') {
						/* Insert ' * ' */
						char_t space = {1,FLAG_COMMENT,' '};
						char_t asterisk = {1,FLAG_COMMENT,'*'};
						env->lines[new_line] = line_insert(env->lines[new_line],space,i,new_line);
						env->lines[new_line] = line_insert(env->lines[new_line],asterisk,i+1,new_line);
						env->lines[new_line] = line_insert(env->lines[new_line],space,i+2,new_line);
						env->col_no += 3;
					}
					break;
				} else if (env->lines[old_line]->text[i].codepoint == ' ' && env->lines[old_line]->text[i+1].codepoint == '*') {
					/* Insert ' * ' */
					char_t space = {1,FLAG_COMMENT,' '};
					char_t asterisk = {1,FLAG_COMMENT,'*'};
					env->lines[new_line] = line_insert(env->lines[new_line],space,i,new_line);
					env->lines[new_line] = line_insert(env->lines[new_line],asterisk,i+1,new_line);
					env->lines[new_line] = line_insert(env->lines[new_line],space,i+2,new_line);
					env->col_no += 3;
					break;
				} else if (env->lines[old_line]->text[i].codepoint == ' ' ||
					env->lines[old_line]->text[i].codepoint == '\t' ||
					env->lines[old_line]->text[i].codepoint == '*') {
					env->lines[new_line] = line_insert(env->lines[new_line],env->lines[old_line]->text[i],i,new_line);
					env->col_no++;
					changed = 1;
				} else {
					break;
				}
			}
		} else {
			int line_to_copy_from = old_line;
			int col;
			if (old_line < new_line &&
				!ignore_brace &&
				(col = line_ends_with_brace(env->lines[old_line])) &&
				env->lines[old_line]->text[col-1].codepoint == '{') {
				line_to_copy_from = find_brace_line_start(old_line+1, col)-1;
			}
			for (int i = 0; i < env->lines[line_to_copy_from]->actual; ++i) {
				if (line_to_copy_from < new_line && i == env->lines[line_to_copy_from]->actual - 3 &&
					env->lines[line_to_copy_from]->text[i].codepoint == ' ' &&
					env->lines[line_to_copy_from]->text[i+1].codepoint == '*' &&
					env->lines[line_to_copy_from]->text[i+2].codepoint == '/') {
					break;
				} else if (env->lines[line_to_copy_from]->text[i].codepoint == ' ' ||
					env->lines[line_to_copy_from]->text[i].codepoint == '\t') {
					env->lines[new_line] = line_insert(env->lines[new_line],env->lines[line_to_copy_from]->text[i],i,new_line);
					env->col_no++;
					changed = 1;
				} else {
					break;
				}
			}
		}
		if (old_line < new_line && !ignore_brace && line_ends_with_brace(env->lines[old_line])) {
			if (env->tabs) {
				char_t c = {0};
				c.codepoint = '\t';
				c.display_width = env->tabstop;
				env->lines[new_line] = line_insert(env->lines[new_line], c, env->col_no-1, new_line);
				env->col_no++;
				changed = 1;
			} else {
				for (int j = 0; j < env->tabstop; ++j) {
					char_t c = {0};
					c.codepoint = ' ';
					c.display_width = 1;
					env->lines[new_line] = line_insert(env->lines[new_line], c, env->col_no-1, new_line);
					env->col_no++;
				}
				changed = 1;
			}
		}
		int was_whitespace = 1;
		for (int i = 0; i < env->lines[old_line]->actual; ++i) {
			if (env->lines[old_line]->text[i].codepoint != ' ' &&
				env->lines[old_line]->text[i].codepoint != '\t') {
				was_whitespace = 0;
				break;
			}
		}
		if (was_whitespace) {
			while (env->lines[old_line]->actual) {
				line_delete(env->lines[old_line], env->lines[old_line]->actual, old_line);
			}
		}
		if (changed) {
			recalculate_syntax(env->lines[new_line],new_line);
		}
	}
}

/**
 * Initialize a buffer with default values.
 *
 * Should be called after creating a buffer.
 */
void setup_buffer(buffer_t * env) {
	/* If this buffer was already initialized, clear out its line data */
	if (env->lines) {
		for (int i = 0; i < env->line_count; ++i) {
			free(env->lines[i]);
		}
		free(env->lines);
	}

	/* Default state parameters */
	env->line_no     = 1; /* Default cursor position */
	env->col_no      = 1;
	env->line_count  = 1; /* Buffers always have at least one line */
	env->modified    = 0;
	env->readonly    = 0;
	env->offset      = 0;
	env->line_avail  = 8; /* Default line buffer capacity */
	env->tabs        = 1; /* Tabs by default */
	env->tabstop     = 4; /* Tab stop width */
	env->indent      = 1; /* Auto-indent by default */
	env->history     = malloc(sizeof(struct history));
	memset(env->history, 0, sizeof(struct history));
	env->last_save_history = env->history;

	/* Allocate line buffer */
	env->lines = malloc(sizeof(line_t *) * env->line_avail);

	/* Initialize the first line */
	env->lines[0] = calloc(sizeof(line_t) + sizeof(char_t) * 32, 1);
	env->lines[0]->available = 32;
}

/**
 * Toggle buffered / unbuffered modes
 */
struct termios old;
void get_initial_termios(void) {
	tcgetattr(STDOUT_FILENO, &old);
}

void set_unbuffered(void) {
	struct termios new = old;
	new.c_iflag &= (~ICRNL) & (~IXON);
	new.c_lflag &= (~ICANON) & (~ECHO) & (~ISIG);
#ifdef VLNEXT
	new.c_cc[VLNEXT] = 0;
#endif
#ifdef VDISCARD
	new.c_cc[VDISCARD] = 0;
#endif
	tcsetattr(STDOUT_FILENO, TCSAFLUSH, &new);
}

void set_buffered(void) {
	tcsetattr(STDOUT_FILENO, TCSAFLUSH, &old);
}

/**
 * Convert codepoint to utf-8 string
 */
int to_eight(uint32_t codepoint, char * out) {
	memset(out, 0x00, 7);

	if (codepoint < 0x0080) {
		out[0] = (char)codepoint;
	} else if (codepoint < 0x0800) {
		out[0] = 0xC0 | (codepoint >> 6);
		out[1] = 0x80 | (codepoint & 0x3F);
	} else if (codepoint < 0x10000) {
		out[0] = 0xE0 | (codepoint >> 12);
		out[1] = 0x80 | ((codepoint >> 6) & 0x3F);
		out[2] = 0x80 | (codepoint & 0x3F);
	} else if (codepoint < 0x200000) {
		out[0] = 0xF0 | (codepoint >> 18);
		out[1] = 0x80 | ((codepoint >> 12) & 0x3F);
		out[2] = 0x80 | ((codepoint >> 6) & 0x3F);
		out[3] = 0x80 | ((codepoint) & 0x3F);
	} else if (codepoint < 0x4000000) {
		out[0] = 0xF8 | (codepoint >> 24);
		out[1] = 0x80 | (codepoint >> 18);
		out[2] = 0x80 | ((codepoint >> 12) & 0x3F);
		out[3] = 0x80 | ((codepoint >> 6) & 0x3F);
		out[4] = 0x80 | ((codepoint) & 0x3F);
	} else {
		out[0] = 0xF8 | (codepoint >> 30);
		out[1] = 0x80 | ((codepoint >> 24) & 0x3F);
		out[2] = 0x80 | ((codepoint >> 18) & 0x3F);
		out[3] = 0x80 | ((codepoint >> 12) & 0x3F);
		out[4] = 0x80 | ((codepoint >> 6) & 0x3F);
		out[5] = 0x80 | ((codepoint) & 0x3F);
	}

	return strlen(out);
}

/**
 * Get the presentation width of a codepoint
 */
int codepoint_width(wchar_t codepoint) {
	if (codepoint == '\t') {
		return 1; /* Recalculate later */
	}
	if (codepoint < 32) {
		/* We render these as ^@ */
		return 2;
	}
	if (codepoint == 0x7F) {
		/* Renders as ^? */
		return 2;
	}
	if (codepoint > 0x7f && codepoint < 0xa0) {
		/* Upper control bytes <xx> */
		return 4;
	}
	if (codepoint == 0xa0) {
		/* Non-breaking space _ */
		return 1;
	}
	/* Skip wcwidth for anything under 256 */
	if (codepoint > 127) {
		if (global_config.can_unicode) {
			/* Higher codepoints may be wider (eg. Japanese) */
			int out = wcwidth(codepoint);
			if (out >= 1) return out;
		}
		/* Invalid character, render as [U+ABCD] or [U+ABCDEF] */
		return (codepoint < 0x10000) ? 8 : 10;
	}
	return 1;
}

/**
 * The following section contains methods for crafting terminal escapes
 * for rendering the display. We do not use curses or any similar
 * library, so we have to generate these sequences ourself based on
 * some assumptions about the target terminal.
 */

/**
 * Move the terminal cursor
 */
void place_cursor(int x, int y) {
	printf("\033[%d;%dH", y, x);
}

/**
 * Given two color codes from a theme, convert them to an escape
 * sequence to set the foreground and background color. This allows
 * us to support basic 16, xterm 256, and true color in themes.
 */
char * color_string(const char * fg, const char * bg) {
	static char output[100];
	char * t = output;
	t += sprintf(t,"\033[22;23;");
	if (*bg == '@') {
		int _bg = atoi(bg+1);
		if (_bg < 10) {
			t += sprintf(t, "4%d;", _bg);
		} else {
			t += sprintf(t, "10%d;", _bg-10);
		}
	} else {
		t += sprintf(t, "48;%s;", bg);
	}
	if (*fg == '@') {
		int _fg = atoi(fg+1);
		if (_fg < 10) {
			t += sprintf(t, "3%dm", _fg);
		} else {
			t += sprintf(t, "9%dm", _fg-10);
		}
	} else {
		t += sprintf(t, "38;%sm", fg);
	}
	return output;
}

/**
 * Set text colors
 *
 * Normally, text colors are just strings, but if they
 * start with @ they will be parsed as integers
 * representing one of the 16 standard colors, suitable
 * for terminals without support for the 256- or 24-bit
 * color modes.
 */
void set_colors(const char * fg, const char * bg) {
	printf("%s", color_string(fg, bg));
}

/**
 * Set just the foreground color
 *
 * (See set_colors above)
 */
void set_fg_color(const char * fg) {
	printf("\033[22;23;");
	if (*fg == '@') {
		int _fg = atoi(fg+1);
		if (_fg < 10) {
			printf("3%dm", _fg);
		} else {
			printf("9%dm", _fg-10);
		}
	} else {
		printf("38;%sm", fg);
	}
}

/**
 * Clear the rest of this line
 */
void clear_to_end(void) {
	if (global_config.can_bce) {
		printf("\033[K");
	}
}

/**
 * For terminals without bce, prepaint the whole line, so we don't have to track
 * where the cursor is for everything. Inefficient, but effective.
 */
void paint_line(const char * bg) {
	if (!global_config.can_bce) {
		set_colors(COLOR_FG, bg);
		for (int i = 0; i < global_config.term_width; ++i) {
			printf(" ");
		}
		printf("\r");
	}
}

/**
 * Enable bold text display
 */
void set_bold(void) {
	printf("\033[1m");
}

/**
 * Disable bold
 */
void unset_bold(void) {
	printf("\033[22m");
}

/**
 * Enable underlined text display
 */
void set_underline(void) {
	printf("\033[4m");
}

/**
 * Disable underlined text display
 */
void unset_underline(void) {
	printf("\033[24m");
}

/**
 * Reset text display attributes
 */
void reset(void) {
	printf("\033[0m");
}

/**
 * Clear the entire screen
 */
void clear_screen(void) {
	printf("\033[H\033[2J");
}

/**
 * Hide the cursor
 */
void hide_cursor(void) {
	if (global_config.can_hideshow) {
		printf("\033[?25l");
	}
}

/**
 * Show the cursor
 */
void show_cursor(void) {
	if (global_config.can_hideshow) {
		printf("\033[?25h");
	}
}

/**
 * Store the cursor position
 */
void store_cursor(void) {
	printf("\0337");
}

/**
 * Restore the cursor position.
 */
void restore_cursor(void) {
	printf("\0338");
}

/**
 * Request mouse events
 */
void mouse_enable(void) {
	if (global_config.can_mouse) {
		printf("\033[?1000h");
		if (global_config.can_sgrmouse) {
			printf("\033[?1006h");
		}
	}
}

/**
 * Stop mouse events
 */
void mouse_disable(void) {
	if (global_config.can_mouse) {
		if (global_config.can_sgrmouse) {
			printf("\033[?1006l");
		}
		printf("\033[?1000l");
	}
}

/**
 * Shift the screen up one line
 */
void shift_up(int amount) {
	printf("\033[%dS", amount);
}

/**
 * Shift the screen down one line.
 */
void shift_down(int amount) {
	printf("\033[%dT", amount);
}

void insert_lines_at(int line, int count) {
	place_cursor(1, line);
	printf("\033[%dL", count);
}

void delete_lines_at(int line, int count) {
	place_cursor(1, line);
	printf("\033[%dM", count);
}

/**
 * Switch to the alternate terminal screen.
 */
void set_alternate_screen(void) {
	if (global_config.can_altscreen) {
		printf("\033[?1049h");
	}
}

/**
 * Restore the standard terminal screen.
 */
void unset_alternate_screen(void) {
	if (global_config.can_altscreen) {
		printf("\033[?1049l");
	}
}

/**
 * Enable bracketed paste mode.
 */
void set_bracketed_paste(void) {
	if (global_config.can_bracketedpaste) {
		printf("\033[?2004h");
	}
}

/**
 * Disable bracketed paste mode.
 */
void unset_bracketed_paste(void) {
	if (global_config.can_bracketedpaste) {
		printf("\033[?2004l");
	}
}

/**
 * Get the name of just a file from a full path.
 * Returns a pointer within the original string.
 *
 * Called in a few different places where the name of a file
 * is needed from its full path, such as drawing tab names or
 * building HTML files.
 */
char * file_basename(char * file) {
	char * c = strrchr(file, '/');
	if (!c) return file;
	return (c+1);
}

/**
 * Print a tab name with fixed width and modifiers
 * into an output buffer and return the written width.
 */
int draw_tab_name(buffer_t * _env, char * out, int max_width, int * width) {
	uint32_t c, state = 0;
	char * t = _env->file_name ? file_basename(_env->file_name) : "[No Name]";

#define ADD(c) do { \
	*o = c; \
	o++; \
	*o = '\0'; \
	bytes++; \
} while (0)

	char * o = out;
	*o = '\0';

	int bytes = 0;

	if (max_width < 2) return 1;

	ADD(' ');
	(*width)++;

	if (_env->modified) {
		if (max_width < 4) return 1;
		ADD('+');
		(*width)++;
		ADD(' ');
		(*width)++;
	}

	while (*t) {
		/* File names can definitely by UTF-8, and we need to
		 * understand their display width... */
		if (!decode(&state, &c, (unsigned char)*t)) {

			/* But our displayed tab name is also just stored
			 * as UTF-8 again, so we essentially rebuild it... */
			char tmp[7];
			int size = to_eight(c, tmp);
			if (bytes + size > 62) break;
			if (*width + size >= max_width) return 1;

			for (int i = 0; i < size; ++i) {
				ADD(tmp[i]);
			}

			(*width) += codepoint_width(c);

		} else if (state == UTF8_REJECT) {
			state = 0;
		}
		t++;
	}

	if (max_width == *width + 1) return 1;

	ADD(' ');
	(*width)++;

#undef ADD
	return 0;
}

/**
 * Redraw the tabbar, with a tab for each buffer.
 *
 * The active buffer is highlighted.
 */
void redraw_tabbar(void) {
	if (!global_config.tabs_visible) return;
	/* Hide cursor while rendering UI */
	hide_cursor();

	/* Move to upper left */
	place_cursor(1,1);

	paint_line(COLOR_TABBAR_BG);

	/* For each buffer... */
	int offset = 0;

	if (global_config.tab_offset) {
		set_colors(COLOR_NUMBER_FG, COLOR_NUMBER_BG);
		printf("<");
		offset++;
	}

	for (int i = global_config.tab_offset; i < buffers_len; i++) {
		buffer_t * _env = buffers[i];

		if (_env == env) {
			/* If this is the active buffer, highlight it */
			reset();
			set_colors(COLOR_FG, COLOR_BG);
			set_bold();
		} else {
			/* Otherwise use default tab color */
			reset();
			set_colors(COLOR_FG, COLOR_TAB_BG);
			set_underline();
		}

		if (global_config.overlay_mode == OVERLAY_MODE_FILESEARCH) {
			if (global_config.command_buffer->actual) {
				char * f = _env->file_name ? file_basename(_env->file_name) : "";
				/* TODO: Support unicode input here; needs conversion */
				int i = 0;
				for (; i < global_config.command_buffer->actual &&
				      f[i] == global_config.command_buffer->text[i].codepoint; ++i);
				if (global_config.command_buffer->actual == i) {
					set_colors(COLOR_SEARCH_FG, COLOR_SEARCH_BG);
				}
			}
		}


		char title[64];
		int size = 0;
		int filled = draw_tab_name(_env, title, global_config.term_width - offset, &size);

		if (filled) {
			offset += size;
			printf("%s", title);
			set_colors(COLOR_NUMBER_FG, COLOR_NUMBER_BG);
			while (offset != global_config.term_width - 1) {
				printf(" ");
				offset++;
			}
			printf(">");
			break;
		}

		printf("%s", title);

		offset += size;
	}

	/* Reset bold/underline */
	reset();
	/* Fill the rest of the tab bar */
	set_colors(COLOR_FG, COLOR_TABBAR_BG);
	clear_to_end();
}

/**
 * Braindead log10 implementation for figuring out the width of the
 * line number column.
 */
int log_base_10(unsigned int v) {
	int r = (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
		(v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
		(v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
	return r;
}

/**
 * Render a line of text.
 *
 * This handles rendering the actual text content. A full line of text
 * also includes a line number and some padding, but those elements
 * are rendered elsewhere; this method can be used for lines that are
 * not attached to a buffer such as command input lines.
 *
 * width: width of the text display region (term width - line number width)
 * offset: how many cells into the line to start rendering at
 */
void render_line(line_t * line, int width, int offset, int line_no) {
	int i = 0; /* Offset in char_t line data entries */
	int j = 0; /* Offset in terminal cells */

	const char * last_color = NULL;
	int was_selecting = 0, was_searching = 0, was_underlining = 0;

	/* Set default text colors */
	set_colors(COLOR_FG, line->is_current ? COLOR_ALT_BG : COLOR_BG);

	/*
	 * When we are rendering in the middle of a wide character,
	 * we render -'s to fill the remaining amount of the character's width.
	 */
	int remainder = 0;

	int is_spaces = 1;

	/* For each character in the line ... */
	while (i < line->actual) {

		/* If there is remaining text... */
		if (remainder) {

			/* If we should be drawing by now... */
			if (j >= offset) {
				if (was_underlining) printf("\033[24m");
				/* Fill remainder with -'s */
				set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("-");
				set_colors(COLOR_FG, line->is_current ? COLOR_ALT_BG : COLOR_BG);
			}

			/* One less remaining width cell to fill */
			remainder--;

			/* Terminal offset moves forward */
			j++;

			/*
			 * If this was the last remaining character, move to
			 * the next codepoint in the line
			 */
			if (remainder == 0) {
				i++;
			}

			continue;
		}

		/* Get the next character to draw */
		char_t c = line->text[i];

		if (c.codepoint != ' ') is_spaces = 0;

		/* If we should be drawing by now... */
		if (j >= offset) {

			/* If this character is going to fall off the edge of the screen... */
			if (j - offset + c.display_width >= width) {
				/* We draw this with special colors so it isn't ambiguous */
				set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				if (was_underlining) printf("\033[24m");

				/* If it's wide, draw ---> as needed */
				while (j - offset < width - 1) {
					printf("-");
					j++;
				}

				/* End the line with a > to show it overflows */
				printf(">");
				set_colors(COLOR_FG, COLOR_BG);
				return;
			}

			/* Syntax highlighting */
			const char * color = flag_to_color(c.flags);

			if (c.flags & FLAG_SELECT) {
				if ((c.flags & FLAG_MASK_COLORS) == FLAG_NONE) color = COLOR_SELECTFG;
				set_colors(color, COLOR_SELECTBG);
				was_selecting = 1;
			} else if ((c.flags & FLAG_SEARCH) || (c.flags == FLAG_NOTICE)) {
				set_colors(COLOR_SEARCH_FG, COLOR_SEARCH_BG);
				was_searching = 1;
			} else if (c.flags == FLAG_ERROR) {
				set_colors(COLOR_ERROR_FG, COLOR_ERROR_BG);
				was_searching = 1; /* co-opting this should work... */
			} else {
				if (was_selecting || was_searching) {
					was_selecting = 0;
					was_searching = 0;
					set_colors(color, line->is_current ? COLOR_ALT_BG : COLOR_BG);
					last_color = color;
				} else if (!last_color || strcmp(color, last_color)) {
					set_fg_color(color);
					last_color = color;
				}
			}

			if ((c.flags & FLAG_UNDERLINE) && !was_underlining) {
				printf("\033[4m");
				was_underlining = 1;
			} else if (!(c.flags & FLAG_UNDERLINE) && was_underlining) {
				printf("\033[24m");
				was_underlining = 0;
			}

			if ((env->mode == MODE_COL_SELECTION || env->mode == MODE_COL_INSERT) &&
				line_no >= ((env->start_line < env->line_no) ? env->start_line : env->line_no) &&
				line_no <= ((env->start_line < env->line_no) ? env->line_no : env->start_line) &&
				((j == env->sel_col) ||
				(j < env->sel_col && j + c.display_width > env->sel_col))) {
				set_colors(COLOR_SELECTFG, COLOR_SELECTBG);
				was_selecting = 1;
			}

#define _set_colors(fg,bg) \
	if (!(c.flags & FLAG_SELECT) && !(c.flags & FLAG_SEARCH) && !(was_selecting)) { \
		set_colors(fg,(line->is_current && bg == COLOR_BG) ? COLOR_ALT_BG : bg); \
	}

			/* Render special characters */
			if (c.codepoint == '\t') {
				_set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("%s", global_config.tab_indicator);
				for (int i = 1; i < c.display_width; ++i) {
					printf("%s" ,global_config.space_indicator);
				}
				_set_colors(last_color ? last_color : COLOR_FG, COLOR_BG);
			} else if (c.codepoint < 32) {
				/* Codepoints under 32 to get converted to ^@ escapes */
				_set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("^%c", '@' + c.codepoint);
				_set_colors(last_color ? last_color : COLOR_FG, COLOR_BG);
			} else if (c.codepoint == 0x7f) {
				_set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("^?");
				_set_colors(last_color ? last_color : COLOR_FG, COLOR_BG);
			} else if (c.codepoint > 0x7f && c.codepoint < 0xa0) {
				_set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("<%2x>", c.codepoint);
				_set_colors(last_color ? last_color : COLOR_FG, COLOR_BG);
			} else if (c.codepoint == 0xa0) {
				_set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("_");
				_set_colors(last_color ? last_color : COLOR_FG, COLOR_BG);
			} else if (c.display_width == 8) {
				_set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("[U+%04x]", c.codepoint);
				_set_colors(last_color ? last_color : COLOR_FG, COLOR_BG);
			} else if (c.display_width == 10) {
				_set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("[U+%06x]", c.codepoint);
				_set_colors(last_color ? last_color : COLOR_FG, COLOR_BG);
			} else if (i > 0 && is_spaces && c.codepoint == ' ' && !(i % env->tabstop)) {
				_set_colors(COLOR_ALT_FG, COLOR_BG); /* Normal background so this is more subtle */
				if (global_config.can_unicode) {
					printf("▏");
				} else {
					printf("|");
				}
				_set_colors(last_color ? last_color : COLOR_FG, COLOR_BG);
			} else if (c.codepoint == ' ' && i == line->actual - 1) {
				/* Special case: space at end of line */
				_set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
				printf("%s",global_config.space_indicator);
				_set_colors(COLOR_FG, COLOR_BG);
			} else {
				/* Normal characters get output */
				char tmp[7]; /* Max six bytes, use 7 to ensure last is always nil */
				to_eight(c.codepoint, tmp);
				printf("%s", tmp);
			}

			/* Advance the terminal cell offset by the render width of this character */
			j += c.display_width;

			/* Advance to the next character */
			i++;
		} else if (c.display_width > 1) {
			/*
			 * If this is a wide character but we aren't ready to render yet,
			 * we may need to draw some filler text for the remainder of its
			 * width to ensure we don't jump around when horizontally scrolling
			 * past wide characters.
			 */
			remainder = c.display_width - 1;
			j++;
		} else {
			/* Regular character, not ready to draw, advance without doing anything */
			j++;
			i++;
		}
	}

	if (was_underlining) printf("\033[24m");

	/**
	 * Determine what color the rest of the line should be.
	 */
	if (env->mode != MODE_LINE_SELECTION) {
		/* If we are not selecting, then use the normal background or highlight
		 * the current line if that feature is enabled. */
		if (line->is_current) {
			set_colors(COLOR_FG, COLOR_ALT_BG);
		} else {
			set_colors(COLOR_FG, COLOR_BG);
		}
	} else {
		/* If this line was empty but was part of the selection, we didn't
		 * set the selection color already, so we need to do that here. */
		if (!line->actual) {
			if (env->line_no == line_no ||
				(env->start_line > env->line_no && 
					(line_no >= env->line_no && line_no <= env->start_line)) ||
				(env->start_line < env->line_no &&
					(line_no >= env->start_line && line_no <= env->line_no))) {
				set_colors(COLOR_SELECTFG, COLOR_SELECTBG);
			}
		}
	}

	/**
	 * In column modes, we may need to draw a column select beyond the end
	 * of a given line, so we need to draw up to that point first.
	 */
	if ((env->mode == MODE_COL_SELECTION  || env->mode == MODE_COL_INSERT) &&
		line_no >= ((env->start_line < env->line_no) ? env->start_line : env->line_no) &&
		line_no <= ((env->start_line < env->line_no) ? env->line_no : env->start_line) &&
		j <= env->sel_col &&
		env->sel_col < width) {
		set_colors(COLOR_FG, COLOR_BG);
		while (j < env->sel_col) {
			printf(" ");
			j++;
		}
		set_colors(COLOR_SELECTFG, COLOR_SELECTBG);
		printf(" ");
		j++;
		set_colors(COLOR_FG, COLOR_BG);
	}

	/*
	 * `maxcolumn` renders the background outside of the requested line length
	 * in a different color, with a line at the border between the two.
	 */
	if (env->maxcolumn && line_no > -1 /* ensures we don't do this for command line */) {

		/* Fill out the normal background */
		if (j < offset) j = offset;
		for (; j < width + offset && j < env->maxcolumn; ++j) {
			printf(" ");
		}

		/* Draw the line */
		if (j < width + offset && j == env->maxcolumn) {
			j++;
			set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
			if (global_config.can_unicode) {
				printf("▏"); /* Should this be configurable? */
			} else {
				printf("|");
			}
		}

		/* Fill the rest with the alternate background color */
		set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
	}

	/**
	 * Clear out the rest of the line. If we are the only buffer or the right split,
	 * and our terminal supports `bce`, we can just bce; otherwise write spaces
	 * until we reach the right side of the screen.
	 */
	if (global_config.can_bce && (line_no == -1 || env->left + env->width == global_config.term_width)) {
		clear_to_end();
	} else {
		/* Paint the rest of the line */
		if (j < offset) j = offset;
		for (; j < width + offset; ++j) {
			printf(" ");
		}
	}
}

/**
 * Get the width of the line number region
 */
int num_width(void) {
	if (!env->numbers) return 0;
	int w = log_base_10(env->line_count) + 3;
	if (w < 4) return 4;
	return w;
}

/**
 * Display width of the revision status gutter.
 */
int gutter_width(void) {
	return env->gutter;
}

/**
 * Draw the gutter and line numbers.
 */
void draw_line_number(int x) {
	if (!env->numbers) return;
	/* Draw the line number */
	if (env->lines[x]->is_current) {
		set_colors(COLOR_NUMBER_BG, COLOR_NUMBER_FG);
	} else {
		set_colors(COLOR_NUMBER_FG, COLOR_NUMBER_BG);
	}
	if (global_config.relative_lines && x+1 != env->line_no) {
		x = x+1 - env->line_no;
		x = ((x < 0) ? -x : x)-1;
	}
	int num_size = num_width() - 2; /* Padding */
	for (int y = 0; y < num_size - log_base_10(x + 1); ++y) {
		printf(" ");
	}
	printf("%d%c", x + 1, ((x+1 == env->line_no || global_config.horizontal_shift_scrolling) && env->coffset > 0) ? '<' : ' ');
}

/**
 * Used to highlight the current line after moving the cursor.
 */
void recalculate_current_line(void) {
	int something_changed = 0;
	if (global_config.highlight_current_line) {
		for (int i = 0; i < env->line_count; ++i) {
			if (env->lines[i]->is_current && i != env->line_no-1) {
				env->lines[i]->is_current = 0;
				something_changed = 1;
				redraw_line(i);
			} else if (i == env->line_no-1 && !env->lines[i]->is_current) {
				env->lines[i]->is_current = 1;
				something_changed = 1;
				redraw_line(i);
			}
		}
	} else {
		something_changed = 1;
	}
	if (something_changed && global_config.relative_lines) {
		for (int i = env->offset; i < env->offset + global_config.term_height - global_config.bottom_size - 1 && i < env->line_count; ++i) {
			/* Place cursor for line number */
			place_cursor(1 + gutter_width() + env->left, (i)-env->offset + 1 + global_config.tabs_visible);
			draw_line_number(i);
		}
	}
}

/**
 * Redraw line.
 *
 * This draws the line number as well as the actual text.
 */
void redraw_line(int x) {
	if (env->loading) return;

	/* Determine if this line is visible. */
	if (x - env->offset < 0 || x - env->offset > global_config.term_height - global_config.bottom_size - 1 - global_config.tabs_visible) {
		return;
	}

	/* Calculate offset in screen */
	int j = x - env->offset;

	/* Hide cursor when drawing */
	hide_cursor();

	/* Move cursor to upper left most cell of this line */
	place_cursor(1 + env->left,1 + global_config.tabs_visible + j);

	/* Draw a gutter on the left. */
	if (env->gutter) {
		switch (env->lines[x]->rev_status) {
			case 1:
				set_colors(COLOR_NUMBER_FG, COLOR_GREEN);
				printf(" ");
				break;
			case 2:
				set_colors(COLOR_NUMBER_FG, global_config.color_gutter ? COLOR_SEARCH_BG : COLOR_ALT_FG);
				printf(" ");
				break;
			case 3:
				set_colors(COLOR_NUMBER_FG, COLOR_KEYWORD);
				printf(" ");
				break;
			case 4:
				set_colors(COLOR_ALT_FG, COLOR_RED);
				printf("▆");
				break;
			case 5:
				set_colors(COLOR_KEYWORD, COLOR_RED);
				printf("▆");
				break;
			default:
				set_colors(COLOR_NUMBER_FG, COLOR_ALT_FG);
				printf(" ");
				break;
		}
	}

	draw_line_number(x);

	int should_shift = x + 1 == env->line_no || global_config.horizontal_shift_scrolling || 
			((env->mode == MODE_COL_SELECTION || env->mode == MODE_COL_INSERT) &&
			x + 1 >= ((env->start_line < env->line_no) ? env->start_line : env->line_no) &&
			x + 1 <= ((env->start_line < env->line_no) ? env->line_no : env->start_line));
	

	/*
	 * Draw the line text 
	 * If this is the active line, the current character cell offset should be used.
	 * (Non-active lines are not shifted and always render from the start of the line)
	 */
	render_line(env->lines[x], env->width - gutter_width() - num_width(), should_shift ? env->coffset : 0, x+1);

}

/**
 * Draw a ~ line where there is no buffer text.
 */
void draw_excess_line(int j) {
	place_cursor(1+env->left,1 + global_config.tabs_visible + j);
	paint_line(COLOR_ALT_BG);
	set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
	printf("~");
	if (env->left + env->width == global_config.term_width && global_config.can_bce) {
		clear_to_end();
	} else {
		/* Paint the rest of the line */
		for (int x = 1; x < env->width; ++x) {
			printf(" ");
		}
	}
}

/**
 * Redraw the entire text area
 */
void redraw_text(void) {
	if (!env) return;
	if (!global_config.has_terminal) return;

	/* Hide cursor while rendering */
	hide_cursor();

	/* Figure out the available size of the text region */
	int l = global_config.term_height - global_config.bottom_size - global_config.tabs_visible;
	int j = 0;

	/* Draw each line */
	for (int x = env->offset; j < l && x < env->line_count; x++) {
		redraw_line(x);
		j++;
	}

	/* Draw the rest of the text region as ~ lines */
	for (; j < l; ++j) {
		draw_excess_line(j);
	}
}

static int view_left_offset = 0;
static int view_right_offset = 0;

/**
 * When in split view, draw the other buffer.
 * Has special handling for when the split is
 * on a single buffer.
 */
void redraw_alt_buffer(buffer_t * buf) {
	if (left_buffer == right_buffer) {
		/* draw the opposite view */
		int left, width, offset;
		left = env->left;
		width = env->width;
		offset = env->offset;
		if (left == 0) {
			/* Draw the right side */

			env->left = width;
			env->width = global_config.term_width - width;
			env->offset = view_right_offset;
			view_left_offset = offset;
		} else {
			env->left = 0;
			env->width = global_config.term_width * global_config.split_percent / 100;
			env->offset = view_left_offset;
			view_right_offset = offset;
		}
		redraw_text();

		env->left = left;
		env->width = width;
		env->offset = offset;
	}
	/* Swap out active buffer */
	buffer_t * tmp = env;
	env = buf;
	/* Redraw text */
	redraw_text();
	/* Return original active buffer */
	env = tmp;
}

/**
 * Basically wcswidth() but implemented internally using our
 * own utf-8 decoder to ensure it works properly.
 */
int display_width_of_string(const char * str) {
	uint8_t * s = (uint8_t *)str;

	int out = 0;
	uint32_t c, state = 0;
	while (*s) {
		if (!decode(&state, &c, *s)) {
			out += codepoint_width(c);
		} else if (state == UTF8_REJECT) {
			state = 0;
		}
		s++;
	}

	return out;
}

void statusbar_append_status(int *remaining_width, size_t *filled, char * output, char * base, ...) {
	va_list args;
	va_start(args, base);
	char tmp[100] = {0}; /* should be big enough */
	vsnprintf(tmp, 100, base, args);
	va_end(args);

	int width = display_width_of_string(tmp) + 2;

	size_t totalWidth = strlen(tmp);
	totalWidth += strlen(color_string(COLOR_STATUS_ALT, COLOR_STATUS_BG));
	totalWidth += strlen(color_string(COLOR_STATUS_FG, COLOR_STATUS_BG));
	totalWidth += strlen(color_string(COLOR_STATUS_ALT, COLOR_STATUS_BG));
	totalWidth += 3;

	if (totalWidth + *filled >= 2047) {
		return;
	}

	if (width < *remaining_width) {
		strcat(output,color_string(COLOR_STATUS_ALT, COLOR_STATUS_BG));
		strcat(output,"[");
		strcat(output,color_string(COLOR_STATUS_FG, COLOR_STATUS_BG));
		strcat(output, tmp);
		strcat(output,color_string(COLOR_STATUS_ALT, COLOR_STATUS_BG));
		strcat(output,"]");
		(*remaining_width) -= width;
		(*filled) += totalWidth;
	}
}

int statusbar_build_right(char * right_hand) {
	char tmp[1024] = {0};
	sprintf(tmp, " Line %d/%d Col: %d ", env->line_no, env->line_count, env->col_no);
	int out = display_width_of_string(tmp);
	char * s = right_hand;

	s += sprintf(s, "%s", color_string(COLOR_STATUS_ALT, COLOR_STATUS_BG));
	s += sprintf(s, " Line ");
	s += sprintf(s, "%s", color_string(COLOR_STATUS_FG, COLOR_STATUS_BG));
	s += sprintf(s, "%d/%d ", env->line_no, env->line_count);
	s += sprintf(s, "%s", color_string(COLOR_STATUS_ALT, COLOR_STATUS_BG));
	s += sprintf(s, " Col: ");
	s += sprintf(s, "%s", color_string(COLOR_STATUS_FG, COLOR_STATUS_BG));
	s += sprintf(s, "%d ", env->col_no);

	return out;
}

/**
 * Draw the status bar
 *
 * The status bar shows the name of the file, whether it has modifications,
 * and (in the future) what syntax highlighting mode is enabled.
 *
 * The right side of the status bar shows the line number and column.
 */
void redraw_statusbar(void) {
	if (global_config.hide_statusbar) return;
	if (!global_config.has_terminal) return;
	if (!env) return;
	/* Hide cursor while rendering */
	hide_cursor();

	/* Move cursor to the status bar line (second from bottom */
	place_cursor(1, global_config.term_height - 1);

	/* Set background colors for status line */
	paint_line(COLOR_STATUS_BG);
	set_colors(COLOR_STATUS_FG, COLOR_STATUS_BG);


	/* Pre-render the right hand side of the status bar */
	char right_hand[1024] = {0};
	int right_width = statusbar_build_right(right_hand);

	char status_bits[2048] = {0}; /* Sane maximum */
	size_t filled = 0;

	int remaining_width = global_config.term_width - right_width;

#define ADD(...) do { statusbar_append_status(&remaining_width, &filled, status_bits, __VA_ARGS__); } while (0)
	if (env->syntax) {
		ADD("%s",env->syntax->name);
	}

	/* Print file status indicators */
	if (env->modified) {
		ADD("+");
	}

	if (env->readonly) {
		ADD("ro");
	}

	if (env->crnl) {
		ADD("crnl");
	}

	if (env->tabs) {
		ADD("tabs");
	} else {
		ADD("spaces=%d", env->tabstop);
	}

	if (global_config.yanks) {
		ADD("y:%ld", global_config.yank_count);
	}

	if (env->indent) {
		ADD("indent");
	}

	if (global_config.smart_complete) {
		ADD("complete");
	}

	if (global_config.background_task) {
		ADD("working");
	}

#undef ADD

	uint8_t * file_name = (uint8_t *)(env->file_name ? env->file_name : "[No Name]");
	int file_name_width = display_width_of_string((char*)file_name);

	if (remaining_width > 3) {
		int is_chopped = 0;
		while (remaining_width < file_name_width + 3) {
			is_chopped = 1;
			if ((*file_name & 0xc0) == 0xc0) { /* First byte of a multibyte character */
				file_name++;
				while ((*file_name & 0xc0) == 0x80) file_name++;
			} else {
				file_name++;
			}
			file_name_width = display_width_of_string((char*)file_name);
		}
		if (is_chopped) {
			set_colors(COLOR_ALT_FG, COLOR_STATUS_BG);
			printf("<");
		}
		set_colors(COLOR_STATUS_FG, COLOR_STATUS_BG);
		printf("%s ", file_name);
	}

	printf("%s", status_bits);

	/* Clear the rest of the status bar */
	clear_to_end();

	/* Move the cursor appropriately to draw it */
	place_cursor(global_config.term_width - right_width, global_config.term_height - 1);
	set_colors(COLOR_STATUS_FG, COLOR_STATUS_BG);
	printf("%s",right_hand);
}

/**
 * Redraw the navigation numbers on the right side of the command line
 */
void redraw_nav_buffer(void) {
	if (!global_config.has_terminal) return;
	if (nav_buffer) {
		store_cursor();
		place_cursor(global_config.term_width - nav_buffer - 2, global_config.term_height);
		printf("%s", nav_buf);
		clear_to_end();
		restore_cursor();
	}
}

/**
 * Draw the command line
 *
 * The command line either has input from the user (:quit, :!make, etc.)
 * or shows the INSERT (or VISUAL in the future) mode name.
 */
void redraw_commandline(void) {
	if (!global_config.has_terminal) return;
	if (!env) return;

	/* Hide cursor while rendering */
	hide_cursor();

	/* Move cursor to the last line */
	place_cursor(1, global_config.term_height);

	/* Set background color */
	paint_line(COLOR_BG);
	set_colors(COLOR_FG, COLOR_BG);

	/* If we are in an edit mode, note that. */
	if (env->mode == MODE_INSERT) {
		set_bold();
		printf("-- INSERT --");
		clear_to_end();
		unset_bold();
	} else if (env->mode == MODE_LINE_SELECTION) {
		set_bold();
		printf("-- LINE SELECTION -- (%d:%d)",
			(env->start_line < env->line_no) ? env->start_line : env->line_no,
			(env->start_line < env->line_no) ? env->line_no : env->start_line
		);
		clear_to_end();
		unset_bold();
	} else if (env->mode == MODE_COL_SELECTION) {
		set_bold();
		printf("-- COL SELECTION -- (%d:%d %d)",
			(env->start_line < env->line_no) ? env->start_line : env->line_no,
			(env->start_line < env->line_no) ? env->line_no : env->start_line,
			(env->sel_col)
		);
		clear_to_end();
		unset_bold();
	} else if (env->mode == MODE_COL_INSERT) {
		set_bold();
		printf("-- COL INSERT -- (%d:%d %d)",
			(env->start_line < env->line_no) ? env->start_line : env->line_no,
			(env->start_line < env->line_no) ? env->line_no : env->start_line,
			(env->sel_col)
		);
		clear_to_end();
		unset_bold();
	} else if (env->mode == MODE_REPLACE) {
		set_bold();
		printf("-- REPLACE --");
		clear_to_end();
		unset_bold();
	} else if (env->mode == MODE_CHAR_SELECTION) {
		set_bold();
		printf("-- CHAR SELECTION -- ");
		clear_to_end();
		unset_bold();
	} else if (env->mode == MODE_DIRECTORY_BROWSE) {
		set_bold();
		printf("-- DIRECTORY BROWSE --");
		clear_to_end();
		unset_bold();
	} else {
		clear_to_end();
	}

	redraw_nav_buffer();
}

/**
 * Draw a message on the command line.
 */
void render_commandline_message(char * message, ...) {
	/* varargs setup */
	va_list args;
	va_start(args, message);

	/* Hide cursor while rendering */
	hide_cursor();

	/* Move cursor to the last line */
	place_cursor(1, global_config.term_height);

	/* Set background color */
	paint_line(COLOR_BG);
	set_colors(COLOR_FG, COLOR_BG);

	vprintf(message, args);
	va_end(args);

	/* Clear the rest of the status bar */
	clear_to_end();

	redraw_nav_buffer();
}

BIM_ACTION(redraw_all, 0,
	"Repaint the screen."
,void) {
	if (!env) return;
	redraw_tabbar();
	redraw_text();
	if (left_buffer) {
		redraw_alt_buffer(left_buffer == env ? right_buffer : left_buffer);
	}
	redraw_statusbar();
	redraw_commandline();
	if (global_config.overlay_mode == OVERLAY_MODE_COMMAND ||
	    global_config.overlay_mode == OVERLAY_MODE_SEARCH ||
	    global_config.overlay_mode == OVERLAY_MODE_FILESEARCH) {
		render_command_input_buffer();
	}
}

void pause_for_key(void) {
	int c;
	while ((c = bim_getch())== -1);
	bim_unget(c);
	redraw_all();
}

/**
 * Redraw all screen elements except the other split view.
 */
void redraw_most(void) {
	redraw_tabbar();
	redraw_text();
	redraw_statusbar();
	redraw_commandline();
}

/**
 * Disable screen splitting.
 */
void unsplit(void) {
	if (left_buffer) {
		left_buffer->left = 0;
		left_buffer->width = global_config.term_width;
	}
	if (right_buffer) {
		right_buffer->left = 0;
		right_buffer->width = global_config.term_width;
	}
	left_buffer = NULL;
	right_buffer = NULL;

	redraw_all();
}

/**
 * Update the terminal title bar
 */
void update_title(void) {
	if (!global_config.can_title) return;

	char cwd[1024] = {'/',0};
	getcwd(cwd, 1024);

	for (int i = 1; i < 3; ++i) {
		printf("\033]%d;%s%s (%s) - Bim\007", i, env->file_name ? env->file_name : "[No Name]", env->modified ? " +" : "", cwd);
	}
}

/**
 * Mark this buffer as modified and
 * redraw the status and tabbar if needed.
 */
void set_modified(void) {
	/* If it was already marked modified, no need to do anything */
	if (env->modified) return;

	/* Mark as modified */
	env->modified = 1;

	/* Redraw some things */
	update_title();
	redraw_tabbar();
	redraw_statusbar();
}

/**
 * Draw a message on the status line
 */
void render_status_message(char * message, ...) {
	if (!env) return; /* Don't print when there's no active environment; this usually means a bimrc command tried to print something */
	/* varargs setup */
	va_list args;
	va_start(args, message);

	/* Hide cursor while rendering */
	hide_cursor();

	/* Move cursor to the status bar line (second from bottom */
	place_cursor(1, global_config.term_height - 1);

	/* Set background colors for status line */
	paint_line(COLOR_STATUS_BG);
	set_colors(COLOR_STATUS_FG, COLOR_STATUS_BG);

	/* Process format string */
	vprintf(message, args);
	va_end(args);

	/* Clear the rest of the status bar */
	clear_to_end();
}

/**
 * Draw an error message to the command line.
 */
void render_error(char * message, ...) {
	/* varargs setup */
	va_list args;
	va_start(args, message);

	if (env) {
		/* Hide cursor while rendering */
		hide_cursor();

		/* Move cursor to the command line */
		place_cursor(1, global_config.term_height);

		/* Set appropriate error message colors */
		set_colors(COLOR_ERROR_FG, COLOR_ERROR_BG);

		/* Draw the message */
		vprintf(message, args);
		va_end(args);
		global_config.had_error = 1;
	} else {
		printf("bim: error during startup: ");
		vprintf(message, args);
		va_end(args);
		printf("\n");
	}

}

int is_paren(int c) {
	uint32_t * p = global_config.paren_pairs;
	while (*p) {
		if ((uint32_t)c == *p) return 1;
		p++;
	}
	return 0;
}

#define _rehighlight_parens() do { \
	if (i < 0 || i >= env->line_count) break; \
	for (int j = 0; j < env->lines[i]->actual; ++j) { \
		if (i == line-1 && j == col-1) { \
			env->lines[line-1]->text[col-1].flags |= FLAG_SELECT; \
			continue; \
		} else { \
			env->lines[i]->text[j].flags &= (~FLAG_SELECT); \
		} \
	} \
	redraw_line(i); \
} while (0)

/**
 * If the config option is enabled, find the matching
 * paren character and highlight it with the SELECT
 * colors, clearing out other SELECT values. As we
 * co-opt the SELECT flag, don't do this in selection
 * modes - only in normal and insert modes.
 */
void highlight_matching_paren(void) {
	if (env->mode == MODE_LINE_SELECTION || env->mode == MODE_CHAR_SELECTION) return;
	if (!global_config.highlight_parens) return;
	int line = -1, col = -1;
	if (env->line_no <= env->line_count && env->col_no <= env->lines[env->line_no-1]->actual &&
		is_paren(env->lines[env->line_no-1]->text[env->col_no-1].codepoint)) {
		find_matching_paren(&line, &col, 1);
	} else if (env->line_no <= env->line_count && env->col_no > 1 && is_paren(env->lines[env->line_no-1]->text[env->col_no-2].codepoint)) {
		find_matching_paren(&line, &col, 2);
	}
	if (env->highlighting_paren == -1 && line == -1) return;
	if (env->highlighting_paren > 0) {
		int i = env->highlighting_paren - 1;
		_rehighlight_parens();
	}
	if (env->highlighting_paren != line && line != -1) {
		int i = line - 1;
		_rehighlight_parens();
	}
	env->highlighting_paren = line;
}

/**
 * Recalculate syntax for the matched paren.
 * Useful when entering selection modes.
 */
void unhighlight_matching_paren(void) {
	if (env->highlighting_paren > 0 && env->highlighting_paren <= env->line_count) {
		for (int i = 0; i < env->line_count; i++) {
			for (int j = 0; j < env->lines[i]->actual; ++j) {
				env->lines[i]->text[j].flags &= ~(FLAG_SELECT);
			}
		}
		env->highlighting_paren = -1;
	}
}

/**
 * Move the cursor to the appropriate location based
 * on where it is in the text region.
 *
 * This does some additional math to set the text
 * region horizontal offset.
 */
void place_cursor_actual(void) {

	/* Invalid positions */
	if (env->line_no < 1) env->line_no = 1;
	if (env->col_no  < 1) env->col_no  = 1;

	/* Account for the left hand gutter */
	int num_size = num_width() + gutter_width();
	int x = num_size + 1 - env->coffset;

	/* Determine where the cursor is physically */
	for (int i = 0; i < env->col_no - 1; ++i) {
		char_t * c = &env->lines[env->line_no-1]->text[i];
		x += c->display_width;
	}

	/* y is a bit easier to calculate */
	int y = env->line_no - env->offset + 1;

	int needs_redraw = 0;

	while (y < 2 + global_config.cursor_padding && env->offset > 0) {
		y++;
		env->offset--;
		needs_redraw = 1;
	}

	while (y > 1 + global_config.term_height - global_config.bottom_size - global_config.cursor_padding - global_config.tabs_visible) {
		y--;
		env->offset++;
		needs_redraw = 1;
	}

	if (needs_redraw) {
		redraw_text();
		redraw_tabbar();
		redraw_statusbar();
		redraw_commandline();
	}

	/* If the cursor has gone off screen to the right... */
	if (x > env->width - 1) {
		/* Adjust the offset appropriately to scroll horizontally */
		int diff = x - (env->width - 1);
		env->coffset += diff;
		x -= diff;
		redraw_text();
	}

	/* Same for scrolling horizontally to the left */
	if (x < num_size + 1) {
		int diff = (num_size + 1) - x;
		env->coffset -= diff;
		x += diff;
		redraw_text();
	}

	highlight_matching_paren();
	recalculate_current_line();

	/* Move the actual terminal cursor */
	place_cursor(x+env->left,y - !global_config.tabs_visible);

	/* Show the cursor */
	show_cursor();
}

/**
 * If the screen is split, update the split sizes based
 * on the new terminal width and the user's split_percent setting.
 */
void update_split_size(void) {
	if (!left_buffer) return;
	if (left_buffer == right_buffer) {
		if (left_buffer->left == 0) {
			left_buffer->width = global_config.term_width * global_config.split_percent / 100;
		} else {
			right_buffer->left = global_config.term_width * global_config.split_percent / 100;
			right_buffer->width = global_config.term_width - right_buffer->left;
		}
		return;
	}
	left_buffer->left = 0;
	left_buffer->width = global_config.term_width * global_config.split_percent / 100;
	right_buffer->left = left_buffer->width;
	right_buffer->width = global_config.term_width - left_buffer->width;
}

/**
 * Update screen size
 */
void update_screen_size(void) {
	struct winsize w;
	ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
	global_config.term_width = w.ws_col;
	global_config.term_height = w.ws_row;
	if (env) {
		if (left_buffer) {
			update_split_size();
		} else if (env != left_buffer && env != right_buffer) {
			env->width = w.ws_col;
		}
	}
	for (int i = 0; i < buffers_len; ++i) {
		if (buffers[i] != left_buffer && buffers[i] != right_buffer) {
			buffers[i]->width = w.ws_col;
		}
	}
}

/**
 * Handle terminal size changes
 */
void SIGWINCH_handler(int sig) {
	(void)sig;
	update_screen_size();
	redraw_all();

	signal(SIGWINCH, SIGWINCH_handler);
}

/**
 * Handle suspend
 */
void SIGTSTP_handler(int sig) {
	(void)sig;
	mouse_disable();
	set_buffered();
	reset();
	clear_screen();
	show_cursor();
	unset_bracketed_paste();
	unset_alternate_screen();
	fflush(stdout);

	signal(SIGTSTP, SIG_DFL);
	raise(SIGTSTP);
}

void SIGCONT_handler(int sig) {
	(void)sig;
	set_alternate_screen();
	set_bracketed_paste();
	set_unbuffered();
	update_screen_size();
	mouse_enable();
	redraw_all();
	update_title();
	signal(SIGCONT, SIGCONT_handler);
	signal(SIGTSTP, SIGTSTP_handler);
}

void SIGINT_handler(int sig) {
	krk_currentThread.flags |= KRK_THREAD_SIGNALLED;
	signal(SIGINT,   SIGINT_handler);
}

void try_to_center(void) {
	int half_a_screen = (global_config.term_height - 3) / 2;
	if (half_a_screen < env->line_no) {
		env->offset = env->line_no - half_a_screen;
	} else {
		env->offset = 0;
	}
}

BIM_ACTION(suspend, 0,
	"Suspend bim and the rest of the job it was run in."
,void) {
	kill(0, SIGTSTP);
}

/**
 * Move the cursor to a specific line.
 */
BIM_ACTION(goto_line, ARG_IS_CUSTOM,
	"Jump to the requested line."
,int line) {

	if (line == -1) line = env->line_count;

	/* Respect file bounds */
	if (line < 1) line = 1;
	if (line > env->line_count) line = env->line_count;

	/* Move the cursor / text region offsets */
	env->coffset = 0;
	env->line_no = line;
	env->col_no  = 1;

	if (!env->loading) {
		if (line > env->offset && line < env->offset + global_config.term_height - global_config.bottom_size) {
			place_cursor_actual();
		} else {
			try_to_center();
		}
		redraw_most();
	} else {
		try_to_center();
	}
}


/**
 * Process (part of) a file and add it to a buffer.
 */
void add_buffer(uint8_t * buf, int size) {
	for (int i = 0; i < size; ++i) {
		if (!decode(&state, &codepoint_r, buf[i])) {
			uint32_t c = codepoint_r;
			if (c == '\n') {
				if (!env->crnl && env->lines[env->line_no-1]->actual && env->lines[env->line_no-1]->text[env->lines[env->line_no-1]->actual-1].codepoint == '\r') {
					env->lines[env->line_no-1]->actual--;
					env->crnl = 1;
				}
				env->lines = add_line(env->lines, env->line_no);
				env->col_no = 1;
				env->line_no += 1;
			} else if (env->crnl && c == '\r') {
				continue;
			} else {
				char_t _c;
				_c.codepoint = (uint32_t)c;
				_c.flags = 0;
				_c.display_width = codepoint_width((wchar_t)c);
				line_t * line  = env->lines[env->line_no - 1];
				line_t * nline = line_insert(line, _c, env->col_no - 1, env->line_no-1);
				if (line != nline) {
					env->lines[env->line_no - 1] = nline;
				}
				env->col_no += 1;
			}
		} else if (state == UTF8_REJECT) {
			state = 0;
		}
	}
}

/**
 * Add a raw string to a buffer. Convenience wrapper
 * for add_buffer for nil-terminated strings.
 */
void add_string(char * string) {
	add_buffer((uint8_t*)string,strlen(string));
}

int str_ends_with(const char * haystack, const char * needle) {
	int i = strlen(haystack);
	int j = strlen(needle);

	do {
		if (haystack[i] != needle[j]) return 0;
		if (j == 0) return 1;
		if (i == 0) return 0;
		i--;
		j--;
	} while (1);
}

/**
 * Find a syntax highlighter for the given filename.
 */
struct syntax_definition * match_syntax(char * file) {
	for (struct syntax_definition * s = syntaxes; syntaxes && s->name; ++s) {
		for (char ** ext = s->ext; *ext; ++ext) {
			if (str_ends_with(file, *ext)) return s;
		}
	}

	return NULL;
}

/**
 * Set the syntax configuration by the name of the syntax highlighter.
 */
void set_syntax_by_name(const char * name) {
	if (!strcmp(name,"none")) {
		for (int i = 0; i < env->line_count; ++i) {
			env->lines[i]->istate = -1;
			for (int j = 0; j < env->lines[i]->actual; ++j) {
				env->lines[i]->text[j].flags &= (3 << 5);
			}
		}
		env->syntax = NULL;
		redraw_all();
		return;
	}
	for (struct syntax_definition * s = syntaxes; syntaxes && s->name; ++s) {
		if (!strcmp(name,s->name)) {
			env->syntax = s;
			for (int i = 0; i < env->line_count; ++i) {
				env->lines[i]->istate = -1;
			}
			schedule_complete_recalc();
			redraw_all();
			return;
		}
	}
	render_error("unrecognized syntax type");
}


/**
 * Check if a string is all numbers.
 */
int is_all_numbers(const char * c) {
	while (*c) {
		if (!isdigit(*c)) return 0;
		c++;
	}
	return 1;
}

struct file_listing {
	int type;
	char * filename;
};

int sort_files(const void * a, const void * b) {
	struct file_listing * _a = (struct file_listing *)a;
	struct file_listing * _b = (struct file_listing *)b;

	if (_a->type == _b->type) {
		return strcmp(_a->filename, _b->filename);
	} else {
		return _a->type - _b->type;
	}
}

void read_directory_into_buffer(char * file) {
	DIR * dirp = opendir(file);
	if (!dirp) {
		env->loading = 0;
		return;
	}

	add_string("# Directory listing for `");
	add_string(file);
	add_string("`\n");

	/* Flexible array to hold directory contents */
	int available = 32;
	int count = 0;
	struct file_listing * files = calloc(sizeof(struct file_listing), available);

	/* Read directory */
	struct dirent * ent = readdir(dirp);
	while (ent) {
		struct stat statbuf;
		char * tmp = malloc(strlen(file) + 1 + strlen(ent->d_name) + 1);
		snprintf(tmp, strlen(file) + 1 + strlen(ent->d_name) + 1, "%s/%s", file, ent->d_name);
		stat(tmp, &statbuf);
		int type = (S_ISDIR(statbuf.st_mode)) ? 'd' : 'f';
		if (count + 1 == available) {
			available *= 2; \
			files = realloc(files, sizeof(struct file_listing) * available); \
		} \
		files[count].type = type;
		files[count].filename = strdup(ent->d_name);
		count++;
		ent = readdir(dirp);
		free(tmp);
	}
	closedir(dirp);

	/* Sort directory entries */
	qsort(files, count, sizeof(struct file_listing), sort_files);

	for (int i = 0; i < count; ++i) {
		add_string(files[i].type == 'd' ? "d" : "f");
		add_string(" ");
		add_string(files[i].filename);
		add_string("\n");

		free(files[i].filename);
	}

	free(files);

	env->file_name = strdup(file);
	env->syntax = find_syntax_calculator("dirent");
	schedule_complete_recalc();
	env->readonly = 1;
	env->loading = 0;
	env->mode = MODE_DIRECTORY_BROWSE;
	env->line_no = 1;
	redraw_all();
}

BIM_ACTION(open_file_from_line, 0,
	"When browsing a directory, open the file under the cursor."
,void) {
	if (env->lines[env->line_no-1]->actual < 1) return;
	if (env->lines[env->line_no-1]->text[0].codepoint != 'd' &&
	    env->lines[env->line_no-1]->text[0].codepoint != 'f') return;
	/* Collect file name */
	char * tmp = malloc(strlen(env->file_name) + 1 + env->lines[env->line_no-1]->actual * 7); /* Should be enough */
	memset(tmp, 0, strlen(env->file_name) + 1 + env->lines[env->line_no-1]->actual * 7);
	char * t = tmp;
	/* Start by copying the filename */
	t += sprintf(t, "%s/", env->file_name);
	/* Start from character 2 to skip d/f and space */
	for (int i = 2; i < env->lines[env->line_no-1]->actual; ++i) {
		t += to_eight(env->lines[env->line_no-1]->text[i].codepoint, t);
	}
	*t = '\0';
	/* Normalize */
	char tmp_path[PATH_MAX+1];
	if (!realpath(tmp, tmp_path)) {
		free(tmp);
		return;
	}
	free(tmp);
	/* Open file */
	buffer_t * old_buffer = env;
	open_file(tmp_path);
	buffer_close(old_buffer);
	update_title();
	redraw_all();
}

int line_matches(line_t * line, char * string) {
	uint32_t c = 0, state = 0;
	int i = 0;
	while (*string) {
		if (!decode(&state, &c, *string)) {
			if (i >= line->actual) return 0;
			if (line->text[i].codepoint != c) return 0;
			string++;
			i++;
		} else if (state == UTF8_REJECT) {
			state = 0;
		}
	}
	return 1;
}

void run_onload(buffer_t * env) {
	KrkValue onLoad;
	if (krk_tableGet_fast(&krk_currentThread.module->fields, S("onload"), &onLoad)) {
		krk_push(onLoad);

		int args = 0;
		if (env->file_name) {
			krk_push(OBJECT_VAL(S("filename")));
			krk_push(OBJECT_VAL(krk_copyString(env->file_name,strlen(env->file_name))));
			args++;
		}
		if (env->syntax) {
			krk_push(OBJECT_VAL(S("lang")));
			krk_push(OBJECT_VAL(krk_copyString(env->syntax->name,strlen(env->syntax->name))));
			args++;

			if (env->syntax->krkClass) {
				krk_push(OBJECT_VAL(S("highlighter")));
				krk_push(OBJECT_VAL(env->syntax->krkClass));
				args++;
			}
		}

		if (IS_CLOSURE(onLoad) && AS_CLOSURE(onLoad)->function->requiredArgs == 1) {
			/* Use old ABI if the function accepts one required argument. */
			krk_push(krk_callNativeOnStack(args * 2, &krk_currentThread.stackTop[-args*2], 0, krk_dict_of));
			if (args) {
				krk_swap(args * 2);
				while (args--) {
					krk_pop();
					krk_pop();
				}
			}
			krk_callStack(1);
		} else {
			/* Otherwise use the new API where the function can accepts keyword args. */
			krk_push(KWARGS_VAL(args));
			krk_callStack(args * 2 + 1);
		}
		krk_resetStack();
	}
}

static void render_syntax_async(background_task_t * task) {
	buffer_t * old_env = env;
	env = task->env;
	int line_no = task->_private_i;

	if (env->line_count && line_no < env->line_count) {
		int tmp = env->loading;
		env->loading = 1;
		recalculate_syntax(env->lines[line_no], line_no);
		env->loading = tmp;
		if (env == old_env) {
			redraw_line(line_no);
		}
	}
	env = old_env;
}

static void schedule_complete_recalc(void) {
	if (env->line_count < 1000) {
		for (int i = 0; i < env->line_count; ++i) {
			recalculate_syntax(env->lines[i], i);
		}
		return;
	}

	/* TODO see if there's already a redraw scheduled */
	for (int i = 0; i < env->line_count; ++i) {
		background_task_t * task = malloc(sizeof(background_task_t));
		task->env  = env;
		task->_private_i = i;
		task->func = render_syntax_async;
		task->next = NULL;
		if (global_config.tail_task) {
			global_config.tail_task->next = task;
		}
		global_config.tail_task = task;
		if (!global_config.background_task) {
			global_config.background_task = task;
		}
	}
	redraw_statusbar();
}

/**
 * Create a new buffer from a file.
 */
void open_file(char * file) {
	env = buffer_new();
	env->width = global_config.term_width;
	env->left = 0;
	env->loading = 1;

	setup_buffer(env);

	FILE * f;
	int init_line = -1;

	if (!strcmp(file,"-")) {
		/**
		 * Read file from stdin. stderr provides terminal input.
		 */
		if (isatty(STDIN_FILENO)) {
			if (buffers_len == 1) {
				quit("stdin is a terminal and you tried to open -; not letting you do that");
			}
			close_buffer();
			render_error("stdin is a terminal and you tried to open -; not letting you do that");
			return;
		}
		f = stdin;
		env->modified = 1;
	} else {
		char * l = strrchr(file, ':');
		if (l && is_all_numbers(l+1)) {
			*l = '\0';
			l++;
			init_line = atoi(l);
		}

		char * _file = file;

		if (file[0] == '~') {
			char * home = getenv("HOME");
			if (home) {
				_file = malloc(strlen(file) + strlen(home) + 4); /* Paranoia */
				sprintf(_file, "%s%s", home, file+1);
			}
		}

		if (file_is_open(_file)) {
			if (file != _file) free(_file);
			close_buffer();
			return;
		}

		struct stat statbuf;
		if (!stat(_file, &statbuf) && S_ISDIR(statbuf.st_mode)) {
			read_directory_into_buffer(_file);
			if (file != _file) free(_file);
			return;
		}
		f = fopen(_file, "r");
		if (file != _file) free(_file);
		if (!f && errno != ENOENT) {
			render_error("%s: %s", file, strerror(errno));
			pause_for_key();
			close_buffer();
			return;
		}
		env->file_name = strdup(file);
	}

	if (!f) {
		if (global_config.highlight_on_open) {
			env->syntax = match_syntax(file);
		}
		env->loading = 0;
		if (global_config.go_to_line) {
			goto_line(1);
		}
		if (env->syntax && env->syntax->prefers_spaces) {
			env->tabs = 0;
		}
		update_biminfo(env, 1);
		run_onload(env);
		return;
	}

	uint8_t buf[BLOCK_SIZE];

	state = 0;

	while (!feof(f) && !ferror(f)) {
		size_t r = fread(buf, 1, BLOCK_SIZE, f);
		add_buffer(buf, r);
	}

	if (ferror(f)) {
		env->loading = 0;
		return;
	}

	if (env->line_no && env->lines[env->line_no-1] && env->lines[env->line_no-1]->actual == 0) {
		/* Remove blank line from end */
		env->lines = remove_line(env->lines, env->line_no-1);
	}

	if (global_config.highlight_on_open) {
		env->syntax = match_syntax(file);
		if (!env->syntax) {
			if (line_matches(env->lines[0], "<?xml")) set_syntax_by_name("xml");
			else if (line_matches(env->lines[0], "<!doctype")) set_syntax_by_name("xml");
			else if (line_matches(env->lines[0], "#!/usr/bin/env bash")) set_syntax_by_name("bash");
			else if (line_matches(env->lines[0], "#!/bin/bash")) set_syntax_by_name("bash");
			else if (line_matches(env->lines[0], "#!/bin/sh")) set_syntax_by_name("bash");
			else if (line_matches(env->lines[0], "#!/usr/bin/env python")) set_syntax_by_name("py");
			else if (line_matches(env->lines[0], "#!/usr/bin/env groovy")) set_syntax_by_name("groovy");
		}
		if (!env->syntax && global_config.syntax_fallback) {
			set_syntax_by_name(global_config.syntax_fallback);
		}
		schedule_complete_recalc();
	}

	/* Try to automatically figure out tabs vs. spaces */
	int tabs = 0, spaces = 0;
	for (int i = 0; i < env->line_count; ++i) {
		if (env->lines[i]->actual > 1) { /* Make sure line has at least some text on it */
			if (env->lines[i]->text[0].codepoint == '\t') tabs++;
			if (env->lines[i]->text[0].codepoint == ' ' &&
				env->lines[i]->text[1].codepoint == ' ') /* Ignore spaces at the start of asterisky C comments */
				spaces++;
		}
	}
	if (spaces > tabs) {
		env->tabs = 0;
	} else if (spaces == tabs && env->syntax) {
		env->tabs = env->syntax->prefers_spaces;
	}

	if (spaces > tabs) {
		int one = 0, two = 0, three = 0, four = 0; /* If you use more than that, I don't like you. */
		int lastCount = 0;
		for (int i = 0; i < env->line_count; ++i) {
			if (env->lines[i]->actual > 1 && !line_is_comment(env->lines[i])) {
				/* Count spaces at beginning */
				int c = 0, diff = 0;
				while (c < env->lines[i]->actual && env->lines[i]->text[c].codepoint == ' ') c++;
				if (c > lastCount) {
					diff = c - lastCount;
				} else if (c < lastCount) {
					diff = lastCount - c;
				}
				if (diff == 1) one++;
				if (diff == 2) two++;
				if (diff == 3) three++;
				if (diff == 4) four++;
				lastCount = c;
			}
		}
		if (four > three && four > two && four > one) {
			env->tabstop = 4;
		} else if (three > two && three > one) {
			env->tabstop = 3;
		} else if (two > one) {
			env->tabstop = 2;
		} else {
			env->tabstop = 1;
		}
	}

	env->loading = 0;

	if (global_config.check_git) {
		env->checkgitstatusonwrite = 1;
		git_examine(file);
	}

	for (int i = 0; i < env->line_count; ++i) {
		recalculate_tabs(env->lines[i]);
	}

	if (global_config.go_to_line) {
		if (init_line != -1) {
			goto_line(init_line);
		} else {
			env->line_no = 1;
			env->col_no = 1;
			fetch_from_biminfo(env);
			place_cursor_actual();
			redraw_all();
			set_preferred_column();
		}
	}

	update_biminfo(env, 1);

	fclose(f);

	run_onload(env);
}

/**
 * Clean up the terminal and exit the editor.
 */
void quit(const char * message) {
	mouse_disable();
	set_buffered();
	reset();
	clear_screen();
	show_cursor();
	unset_bracketed_paste();
	unset_alternate_screen();
	krk_freeVM();
	if (message) {
		fprintf(stdout, "%s\n", message);
	}
	exit(0);
}

/**
 * Try to quit, but don't continue if there are
 * modified buffers open.
 */
void try_quit(void) {
	for (int i = 0; i < buffers_len; i++ ) {
		buffer_t * _env = buffers[i];
		if (_env->modified) {
			if (_env->file_name) {
				render_error("Modifications made to file `%s` in tab %d. Aborting.", _env->file_name, i+1);
			} else {
				render_error("Unsaved new file in tab %d. Aborting.", i+1);
			}
			return;
		}
	}
	/* Close all buffers */
	while (buffers_len) {
		buffer_close(buffers[0]);
	}
	quit(NULL);
}

/**
 * Switch to the previous buffer
 */
BIM_ACTION(previous_tab, 0,
	"Switch the previous tab"
,void) {
	buffer_t * last = NULL;
	for (int i = 0; i < buffers_len; i++) {
		buffer_t * _env = buffers[i];
		if (_env == env) {
			if (last) {
				/* Wrap around */
				env = last;
				if (left_buffer && (left_buffer != env && right_buffer != env)) unsplit();
				redraw_all();
				update_title();
				return;
			} else {
				env = buffers[buffers_len-1];
				if (left_buffer && (left_buffer != env && right_buffer != env)) unsplit();
				redraw_all();
				update_title();
				return;
			}
		}
		last = _env;
	}
}

/**
 * Switch to the next buffer
 */
BIM_ACTION(next_tab, 0,
	"Switch to the next tab"
,void) {
	for (int i = 0; i < buffers_len; i++) {
		buffer_t * _env = buffers[i];
		if (_env == env) {
			if (i != buffers_len - 1) {
				env = buffers[i+1];
				if (left_buffer && (left_buffer != env && right_buffer != env)) unsplit();
				redraw_all();
				update_title();
				return;
			} else {
				/* Wrap around */
				env = buffers[0];
				if (left_buffer && (left_buffer != env && right_buffer != env)) unsplit();
				redraw_all();
				update_title();
				return;
			}
		}
	}
}

/**
 * Check for modified lines in a file by examining `git diff` output.
 * This can be enabled globally in bimrc or per environment with the 'git' option.
 */
int git_examine(char * filename) {
	if (env->modified) return 1;
	int fds[2];
	pipe(fds);
	int child = fork();
	if (child == 0) {
		FILE * dev_null = fopen("/dev/null","w");
		close(fds[0]);
		dup2(fds[1], STDOUT_FILENO);
		dup2(fileno(dev_null), STDERR_FILENO);
		char * args[] = {"git","--no-pager","diff","-U0","--no-color","--",filename,NULL};
		exit(execvp("git",args));
	} else if (child < 0) {
		return 1;
	}

	close(fds[1]);
	FILE * f = fdopen(fds[0],"r");

	int line_offset = 0;
	while (!feof(f)) {
		int c = fgetc(f);
		if (c < 0) break;

		if (c == '@' && line_offset == 0) {
			/* Read line offset, count */
			if (fgetc(f) == '@' && fgetc(f) == ' ' && fgetc(f) == '-') {
				/* This algorithm is borrowed from Kakoune and only requires us to parse the @@ line */
				int from_line = 0;
				int from_count = 0;
				int to_line = 0;
				int to_count = 0;
				fscanf(f,"%d",&from_line);
				if (fgetc(f) == ',') {
					fscanf(f,"%d",&from_count);
				} else {
					from_count = 1;
				}
				fscanf(f,"%d",&to_line);
				if (fgetc(f) == ',') {
					fscanf(f,"%d",&to_count);
				} else {
					to_count = 1;
				}

				if (to_line > env->line_count) continue;

				if (from_count == 0 && to_count > 0) {
					/* No -, all + means all of to_count is green */
					for (int i = 0; i < to_count; ++i) {
						env->lines[to_line+i-1]->rev_status = 1; /* Green */
					}
				} else if (from_count > 0 && to_count == 0) {
					/*
					 * No +, all - means we have a deletion. We mark the next line such that it has a red bar at the top
					 * Note that to_line is one lower than the affected line, so we don't need to mess with indexes.
					 */
					if (to_line >= env->line_count) continue;
					env->lines[to_line]->rev_status = 4; /* Red */
				} else if (from_count > 0 && from_count == to_count) {
					/* from = to, all modified */
					for (int i = 0; i < to_count; ++i) {
						env->lines[to_line+i-1]->rev_status = 3; /* Blue */
					}
				} else if (from_count > 0 && from_count < to_count) {
					/* from < to, some modified, some added */
					for (int i = 0; i < from_count; ++i) {
						env->lines[to_line+i-1]->rev_status = 3; /* Blue */
					}
					for (int i = from_count; i < to_count; ++i) {
						env->lines[to_line+i-1]->rev_status = 1; /* Green */
					}
				} else if (to_count > 0 && from_count > to_count) {
					/* from > to, we deleted but also modified some lines */
					env->lines[to_line-1]->rev_status = 5; /* Red + Blue */
					for (int i = 1; i < to_count; ++i) {
						env->lines[to_line+i-1]->rev_status = 3; /* Blue */
					}
				}
			}
		}

		if (c == '\n') {
			line_offset = 0;
			continue;
		}

		line_offset++;
	}

	fclose(f);
	waitpid(-1,NULL,WNOHANG);
	return 0;
}

/**
 * Write file contents to FILE
 */
void output_file(buffer_t * env, FILE * f) {
	int i, j;
	for (i = 0; i < env->line_count; ++i) {
		line_t * line = env->lines[i];
		line->rev_status = 0;
		for (j = 0; j < line->actual; j++) {
			char_t c = line->text[j];
			if (c.codepoint == 0) {
				char buf[1] = {0};
				fwrite(buf, 1, 1, f);
			} else {
				char tmp[8] = {0};
				int i = to_eight(c.codepoint, tmp);
				fwrite(tmp, i, 1, f);
			}
		}
		if (env->crnl) fputc('\r', f);
		fputc('\n', f);
	}
}

/**
 * Write active buffer to file
 */
void write_file(char * file) {
	if (!file) {
		render_error("Need a file to write to.");
		return;
	}

	char * _file = file;

	if (file[0] == '~') {
		char * home = getenv("HOME");
		if (home) {
			_file = malloc(strlen(file) + strlen(home) + 4); /* Paranoia */
			sprintf(_file, "%s%s", home, file+1);
		}
	}


	FILE * f = fopen(_file, "w+");
	if (file != _file) free(_file);

	if (!f) {
		render_error("Failed to open file for writing.");
		return;
	}

	/* Go through each line and convert it back to UTF-8 */
	output_file(env, f);

	fclose(f);

	/* Mark it no longer modified */
	env->modified = 0;
	env->last_save_history = env->history;

	/* If there was no file name set, set one */
	if (!env->file_name) {
		env->file_name = malloc(strlen(file) + 1);
		memcpy(env->file_name, file, strlen(file) + 1);
	}

	if (env->checkgitstatusonwrite) {
		git_examine(file);
	}

	update_title();
	redraw_all();
}

/**
 * Close the active buffer
 */
void close_buffer(void) {
	buffer_t * previous_env = env;
	buffer_t * new_env = buffer_close(env);
	if (new_env == previous_env) {
		/* ?? Failed to close buffer */
		render_error("lolwat");
	}
	if (left_buffer && env == left_buffer) {
		left_buffer = NULL;
		right_buffer->left = 0;
		right_buffer->width = global_config.term_width;
		right_buffer = NULL;
	} else if (left_buffer && env == right_buffer) {
		right_buffer = NULL;
		left_buffer->left = 0;
		left_buffer->width = global_config.term_width;
		left_buffer = NULL;
	}
	/* No more buffers, exit */
	if (!new_env) {
		quit(NULL);
	}

	/* Set the new active buffer */
	env = new_env;

	/* Redraw the screen */
	redraw_all();
	update_title();
}

/**
 * Set the visual column the cursor should attempt to keep
 * when moving up and down based on where the cursor currently is.
 * This should happen whenever the user intentionally changes
 * the cursor's horizontal positioning, such as with left/right
 * arrow keys, word-move, search, mouse, etc.
 */
void set_preferred_column(void) {
	int c = 0;
	for (int i = 0; i < env->lines[env->line_no-1]->actual && i < env->col_no-1; ++i) {
		c += env->lines[env->line_no-1]->text[i].display_width;
	}
	env->preferred_column = c;
}

BIM_ACTION(cursor_down, 0,
	"Move the cursor one line down."
,void) {
	/* If this isn't already the last line... */
	if (env->line_no < env->line_count) {

		/* Move the cursor down */
		env->line_no += 1;

		/* Try to place the cursor horizontally at the preferred column */
		int _x = 0;
		for (int i = 0; i < env->lines[env->line_no-1]->actual; ++i) {
			char_t * c = &env->lines[env->line_no-1]->text[i];
			_x += c->display_width;
			env->col_no = i+1;
			if (_x > env->preferred_column) {
				break;
			}
		}

		if (env->mode == MODE_INSERT && _x <= env->preferred_column) {
			env->col_no = env->lines[env->line_no-1]->actual + 1;
		}

		/*
		 * If the horizontal cursor position exceeds the width the new line,
		 * then move the cursor left to the extent of the new line.
		 *
		 * If we're in insert mode, we can go one cell beyond the end of the line
		 */
		if (env->col_no > env->lines[env->line_no-1]->actual + (env->mode == MODE_INSERT)) {
			env->col_no = env->lines[env->line_no-1]->actual + (env->mode == MODE_INSERT);
			if (env->col_no == 0) env->col_no = 1;
		}

		if (env->loading) return;

		/*
		 * If the screen was scrolled horizontally, unscroll it;
		 * if it will be scrolled on this line as well, that will
		 * be handled by place_cursor_actual
		 */
		int redraw = 0;
		if (env->coffset != 0) {
			env->coffset = 0;
			redraw = 1;
		}

		/* If we've scrolled past the bottom of the screen, scroll the screen */
		if (env->line_no > env->offset + global_config.term_height - global_config.bottom_size - global_config.tabs_visible - global_config.cursor_padding) {
			env->offset += 1;

			/* Tell terminal to scroll */
			if (global_config.can_scroll && !left_buffer) {
				if (!global_config.can_insert) {
					shift_up(1);
					redraw_tabbar();
				} else {
					delete_lines_at(global_config.tabs_visible ? 2 : 1, 1);
				}

				/* A new line appears on screen at the bottom, draw it */
				int l = global_config.term_height - global_config.bottom_size - global_config.tabs_visible;
				if (env->offset + l < env->line_count + 1) {
					redraw_line(env->offset + l-1);
				} else {
					draw_excess_line(l - 1);
				}
			} else {
				redraw_text();
			}
			redraw_statusbar();
			redraw_commandline();
			place_cursor_actual();
			return;
		} else if (redraw) {
			/* Otherwise, if we need to redraw because of coffset change, do that */
			redraw_text();
		}

		set_history_break();

		/* Update the status bar */
		redraw_statusbar();

		/* Place the terminal cursor again */
		place_cursor_actual();
	}
}

BIM_ACTION(cursor_up, 0,
	"Move the cursor up one line."
,void) {
	/* If this isn't the first line already */
	if (env->line_no > 1) {

		/* Move the cursor down */
		env->line_no -= 1;

		/* Try to place the cursor horizontally at the preferred column */
		int _x = 0;
		for (int i = 0; i < env->lines[env->line_no-1]->actual; ++i) {
			char_t * c = &env->lines[env->line_no-1]->text[i];
			_x += c->display_width;
			env->col_no = i+1;
			if (_x > env->preferred_column) {
				break;
			}
		}

		if (env->mode == MODE_INSERT && _x <= env->preferred_column) {
			env->col_no = env->lines[env->line_no-1]->actual + 1;
		}

		/*
		 * If the horizontal cursor position exceeds the width the new line,
		 * then move the cursor left to the extent of the new line.
		 *
		 * If we're in insert mode, we can go one cell beyond the end of the line
		 */
		if (env->col_no > env->lines[env->line_no-1]->actual + (env->mode == MODE_INSERT)) {
			env->col_no = env->lines[env->line_no-1]->actual + (env->mode == MODE_INSERT);
			if (env->col_no == 0) env->col_no = 1;
		}

		if (env->loading) return;

		/*
		 * If the screen was scrolled horizontally, unscroll it;
		 * if it will be scrolled on this line as well, that will
		 * be handled by place_cursor_actual
		 */
		int redraw = 0;
		if (env->coffset != 0) {
			env->coffset = 0;
			redraw = 1;
		}

		int e = (env->offset == 0) ? env->offset : env->offset + global_config.cursor_padding;
		if (env->line_no <= e) {
			env->offset -= 1;

			/* Tell terminal to scroll */
			if (global_config.can_scroll && !left_buffer) {
				if (!global_config.can_insert) {
					shift_down(1);
					redraw_tabbar();
				} else {
					insert_lines_at(global_config.tabs_visible ? 2 : 1, 1);
				}

				/*
				 * The line at the top of the screen should always be real
				 * so we can just call redraw_line here
				 */
				redraw_line(env->offset);
			} else {
				redraw_tabbar();
				redraw_text();
			}
			redraw_statusbar();
			redraw_commandline();
			place_cursor_actual();
			return;
		} else if (redraw) {
			/* Otherwise, if we need to redraw because of coffset change, do that */
			redraw_text();
		}

		set_history_break();

		/* Update the status bar */
		redraw_statusbar();

		/* Place the terminal cursor again */
		place_cursor_actual();
	}
}

BIM_ACTION(cursor_left, 0,
	"Move the cursor one character to the left."
,void) {
	if (env->col_no > 1) {
		env->col_no -= 1;

		/* Update the status bar */
		redraw_statusbar();

		/* Place the terminal cursor again */
		place_cursor_actual();
	}
	set_history_break();
	set_preferred_column();
}

BIM_ACTION(cursor_right, 0,
	"Move the cursor one character to the right."
,void) {

	/* If this isn't already the rightmost column we can reach on this line in this mode... */
	if (env->col_no < env->lines[env->line_no-1]->actual + !!(env->mode == MODE_INSERT)) {
		env->col_no += 1;

		/* Update the status bar */
		redraw_statusbar();

		/* Place the terminal cursor again */
		place_cursor_actual();
	}
	set_history_break();
	set_preferred_column();
}

BIM_ACTION(cursor_home, 0,
	"Move the cursor to the beginning of the line."
,void) {
	env->col_no = 1;
	set_history_break();
	set_preferred_column();

	/* Update the status bar */
	redraw_statusbar();

	/* Place the terminal cursor again */
	place_cursor_actual();
}

BIM_ACTION(cursor_end, 0,
	"Move the cursor to the end of the line, or past the end in insert mode."
,void) {
	env->col_no = env->lines[env->line_no-1]->actual+!!(env->mode == MODE_INSERT);
	set_history_break();
	set_preferred_column();

	/* Update the status bar */
	redraw_statusbar();

	/* Place the terminal cursor again */
	place_cursor_actual();
}

BIM_ACTION(leave_insert, 0,
	"Leave insert modes and return to normal mode."
,void) {
	if (env->col_no > env->lines[env->line_no-1]->actual) {
		env->col_no = env->lines[env->line_no-1]->actual;
		if (env->col_no == 0) env->col_no = 1;
		set_preferred_column();
	}
		set_history_break();
		env->mode = MODE_NORMAL;
		redraw_commandline();
}

struct MatchQualifier {
	int (*matchFunc)(struct MatchQualifier*,uint32_t,int);
	union {
		uint32_t matchChar;
		struct {
			uint32_t * start;
			uint32_t * end;
		} matchSquares;
	};
};

/**
 * Helper for handling smart case sensitivity.
 */
int match_char(struct MatchQualifier * self, uint32_t b, int mode) {
	if (mode == 0) {
		return self->matchChar == b;
	} else if (mode == 1) {
		return tolower(self->matchChar) == tolower(b);
	}
	return 0;
}

int match_squares(struct MatchQualifier * self, uint32_t c, int mode) {
	uint32_t * start = self->matchSquares.start;
	uint32_t * end = self->matchSquares.end;
	uint32_t * t = start;
	int good = 1;
	if (*t == '^') { t++; good = 0; }
	while (t != end) {
		uint32_t test = *t++;
		if (test == '\\' && *t && strchr("\\]",*t)) {
			test = *t++;
		} else if (test == '\\' && *t == 't') {
			test = '\t'; t++;
		}

		if (*t == '-') {
			t++;
			if (t == end) return 0;
			uint32_t right = *t++;
			if (right == '\\' && *t && strchr("\\]",*t)) {
				right = *t++;
			} else if (right == '\\' && *t == 't') {
				right = '\t'; t++;
			}
			if (mode ? (tolower(c) >= tolower(test) && tolower(c) <= tolower(right)) : (c >= test && c <= right)) return good;
		} else {
			if (mode ? (tolower(c) == tolower(test)) : (c == test)) return good;
		}
	}
	return !good;
}

int match_dot(struct MatchQualifier * self, uint32_t c, int mode) {
	return 1;
}

struct BackRef {
	int start;
	int len;
	uint32_t * copy;
};

#define MAX_REFS 10
int regex_matches(line_t * line, int j, uint32_t * needle, int ignorecase, int *len, uint32_t **needleout, int refindex, struct BackRef * refs) {
	int k = j;
	uint32_t * match = needle;
	if (*match == '^') {
		if (j != 0) return 0;
		match++;
	}
	while (k < line->actual + 1) {
		if (needleout && *match == ')') {
			*needleout = match + 1;
			if (len) *len = k - j;
			return 1;
		}
		if (*match == '\0') {
			if (needleout) return 0;
			if (len) *len = k - j;
			return 1;
		}
		if (*match == '$') {
			if (k != line->actual) return 0;
			match++;
			continue;
		}
		if (k == line->actual) break;

		struct MatchQualifier matcher = {match_char, .matchChar=*match};
		if (*match == '.') {
			matcher.matchFunc = match_dot;
			match++;
		} else if (*match == '\\' && strchr("$^/\\.[?]*+()",match[1]) != NULL) {
			matcher.matchChar = match[1];
			match += 2;
		} else if (*match == '\\' && match[1] == 't') {
			matcher.matchChar = '\t';
			match += 2;
		} else if (*match == '[') {
			uint32_t * s = match+1;
			uint32_t * e = s;
			while (*e && *e != ']') {
				if (*e == '\\' && e[1] == ']') e++;
				e++;
			}
			if (!*e) break; /* fail match on unterminated [] sequence */
			match = e + 1;
			matcher.matchFunc = match_squares;
			matcher.matchSquares.start = s;
			matcher.matchSquares.end = e;
		} else if (*match == '(') {
			match++;
			int _len;
			uint32_t * newmatch;
			if (!regex_matches(line, k, match, ignorecase, &_len, &newmatch, 0, NULL)) break;
			match = newmatch;
			if (refindex && refindex < MAX_REFS) {
				refs[refindex].start = k;
				refs[refindex].len = _len;
				refindex++;
			}
			k += _len;
			continue;
		} else {
			match++;
		}
		if (*match == '?') {
			/* Optional */
			match++;
			if (matcher.matchFunc(&matcher, line->text[k].codepoint, ignorecase)) {
				int _len;
				if (regex_matches(line,k+1,match,ignorecase,&_len, needleout, refindex, refs)) {
					if (len) *len = _len + k + 1 - j;
					return 1;
				}
			}
			continue;
		} else if (*match == '+' || *match == '*') {
			/* Must match at least one */
			if (*match == '+') {
				if (!matcher.matchFunc(&matcher, line->text[k].codepoint, ignorecase)) break;
				k++;
			}
			/* Match any */
			match++;
			int greedy = 1;
			if (*match == '?') {
				/* non-greedy */
				match++;
				greedy = 0;
			}

			int _j = k;
			while (_j < line->actual + 1) {
				int _len;
				if (!greedy && regex_matches(line, _j, match, ignorecase, &_len, needleout, refindex, refs)) {
					if (len) *len = _len + _j - j;
					return 1;
				}
				if (_j < line->actual && !matcher.matchFunc(&matcher, line->text[_j].codepoint, ignorecase)) break;
				_j++;
			}
			if (!greedy) return 0;
			while (_j >= k) {
				int _len;
				if (regex_matches(line, _j, match, ignorecase, &_len, needleout, refindex, refs)) {
					if (len) *len = _len + _j - j;
					return 1;
				}
				_j--;
			}
			return 0;
		} else {
			if (!matcher.matchFunc(&matcher, line->text[k].codepoint, ignorecase)) break;
			k++;
		}
	}
	return 0;
}

int subsearch_matches(line_t * line, int j, uint32_t * needle, int ignorecase, int *len) {
	return regex_matches(line, j, needle, ignorecase, len, NULL, 0, NULL);
}

/**
 * Replace text on a given line with other text.
 */
void perform_replacement(int line_no, uint32_t * needle, uint32_t * replacement, int col, int ignorecase, int *out_col, int *line_out) {
	line_t * line = env->lines[line_no-1];
	int j = col;
	while (j < line->actual + 1) {
		int match_len;
		struct BackRef refs[MAX_REFS] = {0};
		if (regex_matches(line,j,needle,ignorecase,&match_len,NULL,1,refs)) {
			refs[0].start = j;
			refs[0].len = match_len;
			for (int i = 0; i < MAX_REFS; ++i) {
				refs[i].copy = malloc(sizeof(uint32_t) * refs[i].len);
				for (int j = 0; j < refs[i].len; ++j) {
					refs[i].copy[j] = line->text[j+refs[i].start].codepoint;
				}
			}

			/* Perform replacement */
			for (int i = 0; i < match_len; ++i) {
				line_delete(line, j+1, line_no-1);
			}
			int t = 0;
			for (uint32_t * r = replacement; *r; ++r) {
				uint32_t rep = *r;
				char_t _c;
				_c.flags = 0;
				line_t * nline = line;
				if (*r == '\\' && r[1] == 't') {
					rep = '\t';
					++r;
				} else if (*r == '\\' && (r[1] == '\\')) {
					rep = r[1];
					++r;
				} else if (*r == '\\' && (r[1] >= '0' && r[1] <= '9')) {
					int i = r[1] - '0';
					++r;
					nline = line;
					for (int k = 0; k < refs[i].len; ++k) {
						_c.codepoint = refs[i].copy[k];
						_c.display_width = codepoint_width(refs[i].copy[k]);
						nline = line_insert(nline, _c, j + t + k, line_no -1);
					}
					t += refs[i].len;
					rep = 0;
				} else if (*r == '\\' && (r[1] == 'n')) {
					++r;
					env->lines = split_line(env->lines, line_no - 1, j + t);
					line_no++;
					line = env->lines[line_no-1];
					j = 0;
					t = 0;
					continue;
				}
				if (rep) {
					_c.codepoint = rep;
					_c.display_width = codepoint_width(rep);
					nline = line_insert(nline, _c, j + t, line_no -1);
					t++;
				}
				if (line != nline) {
					env->lines[line_no-1] = nline;
					line = nline;
				}
			}
			*out_col = j + t;
			*line_out = line_no;
			set_modified();

			for (int i = 0; i < MAX_REFS; ++i) {
				free(refs[i].copy);
			}

			return;
		}
		j++;
	}
	*out_col = -1;
}

#define COMMAND_HISTORY_MAX 255
unsigned char * command_history[COMMAND_HISTORY_MAX] = {NULL};
unsigned char * search_history[COMMAND_HISTORY_MAX] = {NULL};

/**
 * Add a command to the history. If that command was
 * already in history, it is moved to the front of the list;
 * otherwise, the whole list is shifted backwards and
 * overflow is freed up.
 */
void insert_command_history(unsigned char ** which_history, char * cmd) {
	/* See if this is already in the history. */
	size_t amount_to_shift = COMMAND_HISTORY_MAX - 1;
	for (int i = 0; i < COMMAND_HISTORY_MAX && which_history[i]; ++i) {
		if (!strcmp((char*)which_history[i], cmd)) {
			free(which_history[i]);
			amount_to_shift = i;
			break;
		}
	}

	/* Remove last entry that will roll off the stack */
	if (amount_to_shift == COMMAND_HISTORY_MAX - 1) {
		if (which_history[COMMAND_HISTORY_MAX-1]) free(which_history[COMMAND_HISTORY_MAX-1]);
	}

	/* Roll the history */
	memmove(&which_history[1], &which_history[0], sizeof(char *) * (amount_to_shift));

	which_history[0] = (unsigned char*)strdup(cmd);
}

static uint32_t term_colors[] = {
 0x000000, 0xcc0000, 0x3e9a06, 0xc4a000, 0x3465a4, 0x75507b, 0x06989a, 0xeeeeec, 0x555753, 0xef2929, 0x8ae234, 0xfce94f, 0x729fcf, 0xad7fa8, 0x34e2e2,
 0xFFFFFF, 0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f, 0x005f87, 0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f,
 0x008787, 0x0087af, 0x0087d7, 0x0087ff, 0x00af00, 0x00af5f, 0x00af87, 0x00afaf, 0x00afd7, 0x00afff, 0x00d700, 0x00d75f, 0x00d787, 0x00d7af, 0x00d7d7,
 0x00d7ff, 0x00ff00, 0x00ff5f, 0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af, 0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f,
 0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff, 0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f, 0x5faf87, 0x5fafaf, 0x5fafd7,
 0x5fafff, 0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af, 0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff, 0x870000, 0x87005f,
 0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f, 0x875f87, 0x875faf, 0x875fd7, 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af, 0x8787d7,
 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, 0x87afd7, 0x87afff, 0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
 0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af, 0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7,
 0xaf5fff, 0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f, 0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f,
 0xafd787, 0xafd7af, 0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff, 0xd70000, 0xd7005f, 0xd70087, 0xd700af, 0xd700d7,
 0xd700ff, 0xd75f00, 0xd75f5f, 0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af, 0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f,
 0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff, 0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f, 0xd7ff87, 0xd7ffaf, 0xd7ffd7,
 0xd7ffff, 0xff0000, 0xff005f, 0xff0087, 0xff00af, 0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff, 0xff8700, 0xff875f,
 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f, 0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af, 0xffd7d7,
 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, 0xffffff, 0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
 0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e, 0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4,
 0xeeeeee,
};

/**
 * Convert a color setting from terminal format
 * to a hexadecimal color code and add it to the current
 * buffer. This is used for HTML conversion, but could
 * possibly be used for other purposes.
 */
static void html_convert_color(const char * color_string) {
	char tmp[100];
	if (!strncmp(color_string,"2;",2)) {
		/* 24-bit color */
		int red, green, blue;
		sscanf(color_string+2,"%d;%d;%d",&red,&green,&blue);
		sprintf(tmp, "#%02x%02x%02x;", red,green,blue);
	} else if (!strncmp(color_string,"5;",2)) {
		/* 256 colors; needs lookup table */
		int index;
		sscanf(color_string+2,"%d",&index);
		sprintf(tmp,"#%06x;", (unsigned int)term_colors[(index >= 0 && index <= 255) ? index : 0]);
	} else {
		/* 16 colors; needs lookup table */
		int index;
		uint32_t color;
		sscanf(color_string+1,"%d",&index);
		if (index >= 10) {
			index -= 10;
			color = term_colors[index+8];
		} else if (index == 9) {
			color = term_colors[0];
		} else {
			color = term_colors[index];
		}
		sprintf(tmp,"#%06x;", (unsigned int)color);
	}
	add_string(tmp);
	char * italic = strstr(color_string,";3");
	if (italic && italic[2] == '\0') {
		add_string(" font-style: oblique;");
	}
	char * bold = strstr(color_string,";1");
	if (bold && bold[2] == '\0') {
		add_string(" font-weight: bold;");
	}
	char * underline = strstr(color_string,";4");
	if (underline && underline[2] == '\0') {
		add_string(" font-decoration: underline;");
	}
}

int convert_to_html(void) {
	buffer_t * old = env;
	env = buffer_new();
	setup_buffer(env);
	env->loading = 1;

	add_string("<!doctype html>\n");
	add_string("<html>\n");
	add_string("	<head>\n");
	add_string("		<meta charset=\"UTF-8\">\n");
	if (old->file_name) {
		add_string("		<title>");
		add_string(file_basename(old->file_name));
		add_string("</title>\n");
	}
	add_string("		<style>\n");
	add_string("			body {\n");
	add_string("				margin: 0;\n");
	add_string("				-webkit-text-size-adjust: none;\n");
	add_string("				counter-reset: line-no;\n");
	add_string("				background-color: ");
	/* Convert color */
	html_convert_color(COLOR_BG);
	add_string("\n");
	add_string("			}\n");
	add_string("			.ul { text-decoration: underline; }\n");
	for (int i = 0; i < 15; ++i) {
		/* For each of the relevant flags... */
		char tmp[20];
		sprintf(tmp,"			.s%d { color: ", i);
		add_string(tmp);
		/* These are special */
		if (i == FLAG_NOTICE) {
			html_convert_color(COLOR_SEARCH_FG);
			add_string(" background-color: ");
			html_convert_color(COLOR_SEARCH_BG);
		} else if (i == FLAG_ERROR) {
			html_convert_color(COLOR_ERROR_FG);
			add_string(" background-color: ");
			html_convert_color(COLOR_ERROR_BG);
		} else {
			html_convert_color(flag_to_color(i));
		}
		add_string("}\n");
	}
	add_string("			pre {\n");
	add_string("				margin: 0;\n");
	add_string("				white-space: pre-wrap;\n");
	add_string("				font-family: \"DejaVu Sans Mono\", Courier, monospace;\n");
	add_string("				font-size: 10pt;\n");
	add_string("			}\n");
	add_string("			pre>span {\n");
	add_string("				display: inline-block;\n");
	add_string("				width: 100%;\n");
	add_string("			}\n");
	add_string("			pre>span>a::before {\n");
	add_string("				counter-increment: line-no;\n");
	add_string("				content: counter(line-no);\n");
	add_string("				padding-right: 1em;\n");
	add_string("				width: 3em;\n");
	add_string("				display: inline-block;\n");
	add_string("				text-align: right;\n");
	add_string("				background-color: ");
	html_convert_color(COLOR_NUMBER_BG);
	add_string("\n");
	add_string("				color: ");
	html_convert_color(COLOR_NUMBER_FG);
	add_string("\n");
	add_string("			}\n");
	add_string("			pre>span:target {\n");
	add_string("				background-color: ");
	html_convert_color(COLOR_ALT_BG);
	add_string("\n");
	add_string("			}\n");
	add_string("			pre>span:target>a::before {\n");
	add_string("				background-color: ");
	html_convert_color(COLOR_NUMBER_FG);
	add_string("\n");
	add_string("				color: ");
	html_convert_color(COLOR_NUMBER_BG);
	add_string("\n");
	add_string("			}\n");
	for (int i = 1; i <= env->tabstop; ++i) {
		char tmp[20];
		sprintf(tmp, ".tab%d", i);
		add_string("			");
		add_string(tmp);
		add_string(">span {\n");
		add_string("				display: inline-block;\n");
		add_string("				overflow: hidden;\n");
		add_string("				width: 0;\n");
		add_string("				height: 0;\n");
		add_string("			}\n");
		add_string("			");
		add_string(tmp);
		add_string("::after {\n");
		add_string("				content: '»");
		for (int j = 1; j < i; ++j) {
			add_string("·");
		}
		add_string("';\n");
		add_string("				background-color: ");
		html_convert_color(COLOR_ALT_BG);
		add_string("\n");
		add_string("				color: ");
		html_convert_color(COLOR_ALT_FG);
		add_string("\n");
		add_string("			}\n");
	}
	add_string("			.space {\n");
	add_string("				border-left: 1px solid ");
	html_convert_color(COLOR_ALT_FG);
	add_string("\n");
	add_string("				margin-left: -1px;\n");
	add_string("			}\n");
	add_string("		</style>\n");
	add_string("	</head>\n");
	add_string("	<body><pre>\n");

	for (int i = 0; i < old->line_count; ++i) {
		char tmp[100];
		sprintf(tmp, "<span id=\"L%d\"><a href=\"#L%d\"></a>", i+1, i+1);
		add_string(tmp);
		int last_flag = -1;
		int opened = 0;
		int all_spaces = 1;
		for (int j = 0; j < old->lines[i]->actual; ++j) {
			char_t c = old->lines[i]->text[j];

			if (c.codepoint != ' ') all_spaces = 0;

			if (last_flag == -1 || last_flag != (c.flags & 0x1F)) {
				if (opened) add_string("</span>");
				opened = 1;
				char tmp[100];
				sprintf(tmp, "<span class=\"s%d%s\">",
					c.flags & FLAG_MASK_COLORS,
					(c.flags & FLAG_UNDERLINE) ? " ul" : "");
				add_string(tmp);
				last_flag = (c.flags & 0x1F);
			}

			if (c.codepoint == '<') {
				add_string("&lt;");
			} else if (c.codepoint == '>') {
				add_string("&gt;");
			} else if (c.codepoint == '&') {
				add_string("&amp;");
			} else if (c.codepoint == '\t') {
				char tmp[100];
				sprintf(tmp, "<span class=\"tab%d\"><span>	</span></span>",c.display_width);
				add_string(tmp);
			} else if (j > 0 && c.codepoint == ' ' && all_spaces && !(j % old->tabstop)) {
				add_string("<span class=\"space\"> </span>");
			} else {
				char tmp[7] = {0}; /* Max six bytes, use 7 to ensure last is always nil */
				to_eight(c.codepoint, tmp);
				add_string(tmp);
			}
		}
		if (opened) {
			add_string("</span>");
		} else {
			add_string("<wbr>");
		}
		add_string("</span>\n");
	}

	add_string("</pre></body>\n");
	add_string("</html>\n");

	env->loading = 0;
	env->modified = 1;
	if (old->file_name) {
		char * base = file_basename(old->file_name);
		char * tmp = malloc(strlen(base) + 5);
		*tmp = '\0';
		strcat(tmp, base);
		strcat(tmp, ".htm");
		env->file_name = tmp;
	}
	for (int i = 0; i < env->line_count; ++i) {
		recalculate_tabs(env->lines[i]);
	}
	env->syntax = match_syntax(".htm");
	schedule_complete_recalc();

	return 0;
}

/**
 * Based on vim's :TOhtml
 * Convert syntax-highlighted buffer contents to HTML.
 */
BIM_COMMAND(tohtml,"tohtml","Convert the document to an HTML representation with syntax highlighting.") {
	convert_to_html();

	redraw_all();
	return 0;
}

BIM_ALIAS("TOhtml",tohtml,tohtml)

int _prefix_command_run_script(char * cmd) {
	if (env->mode == MODE_LINE_SELECTION) {
		int range_top, range_bot;
		range_top = env->start_line < env->line_no ? env->start_line : env->line_no;
		range_bot = env->start_line < env->line_no ? env->line_no : env->start_line;

		int in[2];
		pipe(in);
		int out[2];
		pipe(out);
		int child = fork();

		/* Open child process and set up pipes */
		if (child == 0) {
			FILE * dev_null = fopen("/dev/null","w"); /* for stderr */
			close(out[0]);
			close(in[1]);
			dup2(out[1], STDOUT_FILENO);
			dup2(in[0], STDIN_FILENO);
			dup2(fileno(dev_null), STDERR_FILENO);
			system(&cmd[1]); /* Yes we can just do this */
			exit(1);
		} else if (child < 0) {
			render_error("Failed to fork");
			return 1;
		}
		close(out[1]);
		close(in[0]);

		/* Write lines to child process */
		FILE * f = fdopen(in[1],"w");
		for (int i = range_top; i <= range_bot; ++i) {
			line_t * line = env->lines[i-1];
			for (int j = 0; j < line->actual; j++) {
				char_t c = line->text[j];
				if (c.codepoint == 0) {
					char buf[1] = {0};
					fwrite(buf, 1, 1, f);
				} else {
					char tmp[8] = {0};
					int i = to_eight(c.codepoint, tmp);
					fwrite(tmp, i, 1, f);
				}
			}
			fputc('\n', f);
		}
		fclose(f);
		close(in[1]);

		/* Read results from child process into a new buffer */
		FILE * result = fdopen(out[0],"r");
		buffer_t * old = env;
		env = buffer_new();
		setup_buffer(env);
		env->loading = 1;
		uint8_t buf[BLOCK_SIZE];
		state = 0;
		while (!feof(result) && !ferror(result)) {
			size_t r = fread(buf, 1, BLOCK_SIZE, result);
			add_buffer(buf, r);
		}
		if (env->line_no && env->lines[env->line_no-1] && env->lines[env->line_no-1]->actual == 0) {
			env->lines = remove_line(env->lines, env->line_no-1);
		}
		fclose(result);
		waitpid(-1,NULL,WNOHANG);
		env->loading = 0;

		/* Return to the original buffer and replace the selected lines with the output */
		buffer_t * new = env;
		env = old;
		for (int i = range_top; i <= range_bot; ++i) {
			/* Remove the existing lines */
			env->lines = remove_line(env->lines, range_top-1);
		}
		for (int i = 0; i < new->line_count; ++i) {
			/* Add the new lines */
			env->lines = add_line(env->lines, range_top + i - 1);
			replace_line(env->lines, range_top + i - 1, new->lines[i]);
			recalculate_tabs(env->lines[range_top+i-1]);
		}

		env->modified = 1;

		/* Close the temporary buffer */
		buffer_close(new);
	} else {
		/* Reset and draw some line feeds */
		reset();
		printf("\n\n");

		/* Set buffered for shell application */
		set_buffered();

		/* Call the shell and wait for completion */
		system(&cmd[1]);

		/* Return to the editor, wait for user to press enter. */
		set_unbuffered();
		printf("\n\nPress ENTER to continue.");
		int c;
		while ((c = bim_getch(), c != ENTER_KEY && c != LINE_FEED));

		/* Redraw the screen */
		redraw_all();
	}

	/* Done processing command */
	return 0;
}

int replace_text(int range_top, int range_bot, char divider, char * needle) {
	char * c = needle;
	char * replacement = NULL;
	char * options = "";

	while (*c) {
		if (*c == divider) {
			*c = '\0';
			replacement = c + 1;
			break;
		}
		c++;
	}

	if (!replacement) {
		render_error("nothing to replace with");
		return 1;
	}

	c = replacement;
	while (*c) {
		if (*c == divider) {
			*c = '\0';
			options = c + 1;
			break;
		}
		c++;
	}

	int global = 0;
	int case_insensitive = 0;

	/* Parse options */
	while (*options) {
		switch (*options) {
			case 'g':
				global = 1;
				break;
			case 'i':
				case_insensitive = 1;
				break;
		}
		options++;
	}

	uint32_t * needle_c = malloc(sizeof(uint32_t) * (strlen(needle) + 1));
	uint32_t * replacement_c = malloc(sizeof(uint32_t) * (strlen(replacement) + 1));

	{
		int i = 0;
		uint32_t c, state = 0;
		for (char * cin = needle; *cin; cin++) {
			if (!decode(&state, &c, *cin)) {
				needle_c[i] = c;
				i++;
			} else if (state == UTF8_REJECT) {
				state = 0;
			}
		}
		needle_c[i] = 0;
		i = 0;
		c = 0;
		state = 0;
		for (char * cin = replacement; *cin; cin++) {
			if (!decode(&state, &c, *cin)) {
				replacement_c[i] = c;
				i++;
			} else if (state == UTF8_REJECT) {
				state = 0;
			}
		}
		replacement_c[i] = 0;
	}

	int replacements = 0;
	for (int line = range_top; line <= range_bot; ++line) {
		int col = 0;
		while (col != -1) {
			int _line = line;
			perform_replacement(line, needle_c, replacement_c, col, case_insensitive, &col, &_line);
			if (col != -1) replacements++;
			if (_line > line) {
				range_bot += _line - line;
				line = _line;
			}
			if (!global) break;
		}
	}
	if (env->mode == MODE_LINE_SELECTION) {
		env->start_line = env->start_line < env->line_no ? range_top : range_bot;
		env->line_no    = env->start_line < env->line_no ? range_bot : range_top;
	}
	free(needle_c);
	free(replacement_c);
	if (replacements) {
		render_status_message("replaced %d instance%s of %s", replacements, replacements == 1 ? "" : "s", needle);
		set_history_break();
		redraw_text();
	} else {
		render_error("Pattern not found: %s", needle);
	}

	return 0;
}

BIM_PREFIX_COMMAND(repsome,"s","Perform a replacement over selected lines") {
	int range_top, range_bot;
	if (env->mode == MODE_LINE_SELECTION) {
		range_top = env->start_line < env->line_no ? env->start_line : env->line_no;
		range_bot = env->start_line < env->line_no ? env->line_no : env->start_line;
	} else {
		range_top = env->line_no;
		range_bot = env->line_no;
	}
	return replace_text(range_top, range_bot, cmd[1], &cmd[2]);
}

BIM_PREFIX_COMMAND(repall,"%s","Perform a replacement over the entire file.") {
	return replace_text(1, env->line_count, cmd[2], &cmd[3]);
}

BIM_COMMAND(e,"e","Open a file") {
	if (argc > 1) {
		/* This actually opens a new tab */
		open_file(argv[1]);
		update_title();
	} else {
		if (env->modified) {
			render_error("File is modified, can not reload.");
			return 1;
		}

		if (!env->file_name) {
			render_error("No file name.");
			return 1;
		}

		buffer_t * old_env = env;
		open_file(env->file_name);
		buffer_t * new_env = env;
		env = old_env;

#define SWAP(T,a,b) do { T x = a; a = b; b = x; } while (0)
		SWAP(line_t **, env->lines, new_env->lines);
		SWAP(int, env->line_count, new_env->line_count);
		SWAP(int, env->line_avail, new_env->line_avail);
		SWAP(history_t *, env->history, new_env->history);

		buffer_close(new_env); /* Should probably also free, this needs editing. */
		schedule_complete_recalc();
		redraw_all();
	}
	return 0;
}

BIM_COMMAND(tabnew,"tabnew","Open a new tab") {
	if (argc > 1) {
		open_file(argv[1]);
		update_title();
	} else {
		env = buffer_new();
		setup_buffer(env);
		redraw_all();
		update_title();
	}
	return 0;
}

BIM_COMMAND(w,"w","Write a file") {
	/* w: write file */
	if (argc > 1) {
		write_file(argv[1]);
	} else {
		write_file(env->file_name);
	}
	return 0;
}

BIM_COMMAND(wq,"wq","Write and close buffer") {
	write_file(env->file_name);
	close_buffer();
	return 0;
}

BIM_COMMAND(history,"history","Display command history") {
	render_commandline_message(""); /* To clear command line */
	for (int i = COMMAND_HISTORY_MAX; i > 1; --i) {
		if (command_history[i-1]) render_commandline_message("%d:%s\n", i-1, command_history[i-1]);
	}
	render_commandline_message("\n");
	redraw_tabbar();
	redraw_commandline();
	pause_for_key();
	return 0;
}

BIM_COMMAND(q,"q","Close buffer") {
	if (left_buffer && left_buffer == right_buffer) {
		unsplit();
		return 0;
	}
	if (env->modified) {
		render_error("No write since last change. Use :q! to force exit.");
	} else {
		close_buffer();
	}
	update_title();
	return 0;
}

BIM_COMMAND(qbang,"q!","Force close buffer") {
	close_buffer();
	update_title();
	return 0;
}

BIM_COMMAND(qa,"qa","Try to close all buffers") {
	try_quit();
	return 0;
}

BIM_ALIAS("qall",qall,qa)

BIM_COMMAND(qabang,"qa!","Force exit") {
	/* Forcefully exit editor */
	while (buffers_len) {
		buffer_close(buffers[0]);
	}
	quit(NULL);
	return 1; /* doesn't return */
}

BIM_COMMAND(tabp,"tabp","Previous tab") {
	previous_tab();
	update_title();
	return 0;
}

BIM_COMMAND(tabn,"tabn","Next tab") {
	next_tab();
	update_title();
	return 0;
}

BIM_COMMAND(tabm,"tabm","Move the current tab to a new index") {
	/* Figure out the current index */
	int i = 0;
	for (; i < buffers_len; i++) {
		if (buffers[i] == env) break;
	}

	if (i == buffers_len) {
		render_status_message("(invalid state?)");
		return 1;
	}

	if (argc < 2) {
		render_status_message("tab = %d", i);
		return 1;
	}

	int newIndex = atoi(argv[1]);

	if (newIndex == i) {
		return 0;
	}

	/* Okay, this is stupid, but, remove the buffer */
	memmove(&buffers[i], &buffers[i+1], sizeof(*buffers) * (buffers_len - i -1));
	/* Then make space at the destination */
	memmove(&buffers[newIndex+1], &buffers[newIndex], sizeof(*buffers) * (buffers_len - newIndex -1));

	buffers[newIndex] = env;

	redraw_tabbar();
	update_title();
	return 0;
}

BIM_COMMAND(tab,"tab", "Open a specific tab") {
	if (argc < 2) return bim_command_tabm("tabm", argc, argv);
	int i = atoi(argv[1]);

	if (i < 0 || i > buffers_len) {
		render_error("Invalid tab index");
		return 1;
	}

	env = buffers[i];
	if (left_buffer && (left_buffer != env && right_buffer != env)) unsplit();
	redraw_all();
	update_title();
	return 0;
}

BIM_COMMAND(tabindicator,"tabindicator","Set the tab indicator") {
	if (argc < 2) {
		render_status_message("tabindicator=%s", global_config.tab_indicator);
		return 0;
	}
	if (!global_config.can_unicode && strlen(argv[1]) != 1) return 0;
	if (display_width_of_string(argv[1]) != 1) {
		render_error("Can't set '%s' as indicator, must be one cell wide.", argv[1]);
		return 1;
	}
	if (global_config.tab_indicator) free(global_config.tab_indicator);
	global_config.tab_indicator = strdup(argv[1]);
	return 0;
}

BIM_COMMAND(spaceindicator,"spaceindicator","Set the space indicator") {
	if (argc < 2) {
		render_status_message("spaceindicator=%s", global_config.space_indicator);
		return 0;
	}
	if (!global_config.can_unicode && strlen(argv[1]) != 1) return 0;
	if (display_width_of_string(argv[1]) != 1) {
		render_error("Can't set '%s' as indicator, must be one cell wide.", argv[1]);
		return 1;
	}
	if (global_config.space_indicator) free(global_config.space_indicator);
	global_config.space_indicator = strdup(argv[1]);
	return 0;
}

BIM_COMMAND(global_git,"global.git","Show or change the default status of git integration") {
	if (argc < 2) {
		render_status_message("global.git=%d", global_config.check_git);
	} else {
		global_config.check_git = !!atoi(argv[1]);
	}
	return 0;
}

BIM_COMMAND(git,"git","Show or change status of git integration") {
	if (!env) {
		render_error("requires environment (did you mean global.git?)");
		return 1;
	}
	if (argc < 2) {
		render_status_message("git=%d", env->checkgitstatusonwrite);
	} else {
		env->checkgitstatusonwrite = !!atoi(argv[1]);
		if (env->checkgitstatusonwrite && !env->modified && env->file_name) {
			git_examine(env->file_name);
			redraw_text();
		}
	}
	return 0;
}

BIM_COMMAND(colorgutter,"colorgutter","Show or change status of gutter colorization for unsaved modifications") {
	if (argc < 2) {
		render_status_message("colorgutter=%d", global_config.color_gutter);
	} else {
		global_config.color_gutter = !!atoi(argv[1]);
		redraw_text();
	}
	return 0;
}

BIM_COMMAND(indent,"indent","Enable smart indentation") {
	env->indent = 1;
	redraw_statusbar();
	return 0;
}

BIM_COMMAND(noindent,"noindent","Disable smart indentation") {
	env->indent = 0;
	redraw_statusbar();
	return 0;
}

/* TODO: global.maxcolumn */
BIM_COMMAND(maxcolumn,"maxcolumn","Highlight past the given column to indicate maximum desired line length") {
	if (argc < 2) {
		render_status_message("maxcolumn=%d",env->maxcolumn);
		return 0;
	}
	env->maxcolumn = atoi(argv[1]);
	redraw_text();
	return 0;
}

BIM_COMMAND(cursorcolumn,"cursorcolumn","Show the visual column offset of the cursor.") {
	render_status_message("cursorcolumn=%d", env->preferred_column);
	return 0;
}

BIM_COMMAND(noh,"noh","Clear search term") {
	if (global_config.search) {
		free(global_config.search);
		global_config.search = NULL;
		for (int i = 0; i < env->line_count; ++i) {
			for (int j = 0; j < env->lines[i]->actual; ++j) {
				env->lines[i]->text[j].flags &= ~(FLAG_SEARCH);
			}
		}
		redraw_text();
	}
	return 0;
}

BIM_COMMAND(help,"help","Show help text.") {
	if (argc < 2) {
		render_commandline_message(""); /* To clear command line */
		render_commandline_message("\n");
		render_commandline_message(" \033[1mbim - a text editor \033[22m\n");
		render_commandline_message("\n");
		render_commandline_message(" Available commands:\n");
		render_commandline_message("   Quit with \033[3m:q\033[23m, \033[3m:qa\033[23m, \033[3m:q!\033[23m, \033[3m:qa!\033[23m\n");
		render_commandline_message("   Write out with \033[3m:w \033[4mfile\033[24;23m\n");
		render_commandline_message("   Set syntax with \033[3m:syntax \033[4mlanguage\033[24;23m\n");
		render_commandline_message("   Open a new tab with \033[3m:e \033[4mpath/to/file\033[24;23m\n");
		render_commandline_message("   \033[3m:tabn\033[23m and \033[3m:tabp\033[23m can be used to switch tabs\n");
		render_commandline_message("   Set the color scheme with \033[3m:theme \033[4mtheme\033[24;23m\n");
		render_commandline_message("   Set the behavior of the tab key with \033[3m:tabs\033[23m or \033[3m:spaces\033[23m\n");
		render_commandline_message("   Set tabstop with \033[3m:tabstop \033[4mwidth\033[24;23m\n");
		render_commandline_message("\n");
		render_commandline_message(" Bim %s%s\n", BIM_VERSION, BIM_BUILD_DATE);
		render_commandline_message(" %s\n", BIM_COPYRIGHT);
		render_commandline_message("\n");
	} else {
		int found = 0;
		for (struct command_def * c = regular_commands; !found && regular_commands && c->name; ++c) {
			if (!strcmp(c->name, argv[1])) {
				render_commandline_message(""); /* To clear command line */
				render_commandline_message("Help description for `%s`:\n", c->name);
				render_commandline_message("  %s\n", c->description);
				found = 1;
				break;
			}
		}
		for (struct command_def * c = prefix_commands; !found && prefix_commands && c->name; ++c) {
			if (!strcmp(c->name, argv[1])) {
				render_commandline_message(""); /* To clear command line */
				render_commandline_message("Help description for `%s`:\n", c->name);
				render_commandline_message("  %s\n", c->description);
				found = 1;
				break;
			}
		}
		if (!found) {
			render_error("Unknown command: %s", argv[1]);
			return 1;
		}
	}
	/* Redrawing the tabbar makes it look like we just shifted the whole view up */
	redraw_tabbar();
	redraw_commandline();
	/* Wait for a character so we can redraw the screen before continuing */
	pause_for_key();
	return 0;
}

BIM_COMMAND(version,"version","Show version information.") {
	render_status_message("Bim %s%s", BIM_VERSION, BIM_BUILD_DATE);
	return 0;
}

BIM_COMMAND(theme,"theme","Set color theme") {
	if (argc < 2) {
		render_status_message("theme=%s", current_theme);
	} else {
		for (struct theme_def * d = themes; themes && d->name; ++d) {
			if (!strcmp(argv[1], d->name)) {
				ptrdiff_t before = krk_currentThread.stackTop - krk_currentThread.stack;
				krk_push(OBJECT_VAL(d->callable));
				KrkValue result = krk_callStack(0);
				krk_currentThread.stackTop = krk_currentThread.stack + before;
				if (IS_NONE(result) && (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
					render_error("Exception occurred in theme: %s", AS_INSTANCE(krk_currentThread.currentException)->_class->name->chars);
					krk_dumpTraceback();
					int key = 0;
					while ((key = bim_getkey(DEFAULT_KEY_WAIT)) == KEY_TIMEOUT);
				}
				current_theme = d->name;
				redraw_all();
				return 0;
			}
		}
	}
	return 0;
}

BIM_ALIAS("colorscheme",colorscheme,theme)

BIM_COMMAND(splitpercent,"splitpercent","Display or change view split") {
	if (argc < 2) {
		render_status_message("splitpercent=%d", global_config.split_percent);
		return 0;
	} else {
		global_config.split_percent = atoi(argv[1]);
		if (left_buffer) {
			update_split_size();
			redraw_all();
		}
	}
	return 0;
}

BIM_COMMAND(split,"split","Split the current view.") {
	buffer_t * original = env;
	if (argc > 1) {
		int is_not_number = 0;
		for (char * c = argv[1]; *c; ++c) is_not_number |= !isdigit(*c);
		if (is_not_number) {
			/* Open a file for the new split */
			open_file(argv[1]);
			right_buffer = buffers[buffers_len-1];
		} else {
			/* Use an existing buffer for the new split */
			int other = atoi(argv[1]);
			if (other >= buffers_len || other < 0) {
				render_error("Invalid buffer number: %d", other);
				return 1;
			}
			right_buffer = buffers[other];
		}
	} else {
		/* Use the current buffer for the new split */
		right_buffer = original;
	}
	left_buffer = original;
	update_split_size();
	redraw_all();
	return 0;
}

BIM_COMMAND(unsplit,"uns
Download .txt
gitextract_orn7wwbb/

├── .github/
│   ├── FUNDING.yml
│   ├── SECURITY.md
│   └── workflows/
│       ├── aarch64.yml
│       └── x86_64.yml
├── .gitignore
├── .gitmodules
├── .mailmap
├── AUTHORS
├── LICENSE
├── Makefile
├── README.md
├── apps/
│   ├── about.c
│   ├── basename.c
│   ├── beep.c
│   ├── bim.c
│   ├── bim.h
│   ├── block-dev-stats.c
│   ├── cal.c
│   ├── calculator.c
│   ├── cat-img.c
│   ├── cat.c
│   ├── chmod.c
│   ├── chown.c
│   ├── clear.c
│   ├── cmp.c
│   ├── color-picker.c
│   ├── compositor.c
│   ├── cp.c
│   ├── cpu-name.krk
│   ├── cpuwidget.c
│   ├── crc32.c
│   ├── cursor-off.c
│   ├── date.c
│   ├── dbg.c
│   ├── demo.c
│   ├── demo.krk
│   ├── dhclient.c
│   ├── dirname.c
│   ├── drawlines.c
│   ├── du.c
│   ├── echo.c
│   ├── env.c
│   ├── esh.c
│   ├── false.c
│   ├── fetch.c
│   ├── file-browser.c
│   ├── find-timezone.c
│   ├── font-preview.c
│   ├── font-tool.c
│   ├── free.c
│   ├── getty.c
│   ├── glogin-provider.c
│   ├── glogin.c
│   ├── grep.c
│   ├── groups.c
│   ├── gsudo.c
│   ├── gunzip.c
│   ├── head.c
│   ├── hello.c
│   ├── help-browser.c
│   ├── hexify.c
│   ├── highlight-source.krk
│   ├── hostname.c
│   ├── ifconfig.c
│   ├── imgviewer.c
│   ├── init.c
│   ├── insmod.c
│   ├── irc.c
│   ├── json-test.c
│   ├── julia.c
│   ├── kbd-test.c
│   ├── kcmdline.c
│   ├── kill.c
│   ├── killall.c
│   ├── krk_test_noise.krk
│   ├── krk_yutani_test.krk
│   ├── live-session.c
│   ├── ln.c
│   ├── login-loop.c
│   ├── login.c
│   ├── logname.c
│   ├── ls.c
│   ├── lspci.c
│   ├── maybe-pdfviewer.krk
│   ├── migrate.c
│   ├── mines.krk
│   ├── misaka-test.c
│   ├── mixerctl.c
│   ├── mkdir.c
│   ├── mktemp.c
│   ├── more.c
│   ├── mount.c
│   ├── msk.c
│   ├── mv.c
│   ├── netty.c
│   ├── nproc.c
│   ├── nslookup.c
│   ├── nyancat/
│   │   ├── animation.h
│   │   └── telnet.h
│   ├── nyancat.c
│   ├── package-manager.c
│   ├── panel.c
│   ├── path_demo.krk
│   ├── piano.c
│   ├── pidof.c
│   ├── ping.c
│   ├── plasma.c
│   ├── play.c
│   ├── polygons.c
│   ├── pong.c
│   ├── prompt_and_delete.krk
│   ├── ps.c
│   ├── pstree.c
│   ├── pwd.c
│   ├── qemu-display-hack.c
│   ├── qemu-fwcfg.c
│   ├── readelf.c
│   ├── readlink.c
│   ├── reboot.c
│   ├── reload_desktop.sh
│   ├── reset.c
│   ├── rm.c
│   ├── rmdir.c
│   ├── serial-console.c
│   ├── session.c
│   ├── set-resolution.c
│   ├── set-wallpaper.sh
│   ├── show-toasts.krk
│   ├── show-tutorial.sh
│   ├── showdialog.c
│   ├── sleep.c
│   ├── snow.c
│   ├── sort.c
│   ├── splash-log.c
│   ├── stat.c
│   ├── strace.c
│   ├── strings.c
│   ├── stty.c
│   ├── sudo.c
│   ├── sync.c
│   ├── sysfunc.c
│   ├── sysinfo.c
│   ├── t_mbstowcs.c
│   ├── tar.c
│   ├── tee.c
│   ├── terminal-font.h
│   ├── terminal-palette.h
│   ├── terminal-vga.c
│   ├── terminal.c
│   ├── test-badwrite.c
│   ├── test-conf.c
│   ├── test-fpclassify.c
│   ├── test-ftruncate.c
│   ├── test-localtime.c
│   ├── test-lock.c
│   ├── test-loop.c
│   ├── test-printf.c
│   ├── test-ptrace-syscall.c
│   ├── test-sigsegv.c
│   ├── test-sigsuspend.c
│   ├── test-sigwait.c
│   ├── test-syscall-sysret.c
│   ├── test-tls.c
│   ├── test-tty-read.c
│   ├── test-udp-recv.krk
│   ├── toaru_logo.h
│   ├── toast.krk
│   ├── toastd.c
│   ├── toggle-abs-mouse.c
│   ├── top.c
│   ├── touch.c
│   ├── true.c
│   ├── tty.c
│   ├── ttysize.c
│   ├── tutorial.c
│   ├── uname.c
│   ├── ununicode.h
│   ├── upload.krk
│   ├── uptime.c
│   ├── vga-palette.h
│   ├── wallpaper-picker.c
│   ├── wc.c
│   ├── weather-configurator.c
│   ├── weather-tool.c
│   ├── which.c
│   ├── whoami.c
│   ├── yes.c
│   ├── yutani-clipboard.c
│   ├── yutani-kbd.c
│   ├── yutani-query.c
│   ├── yutani-test.c
│   ├── yutani-tty-pipe.c
│   └── zcat.c
├── base/
│   ├── etc/
│   │   ├── demo.conf
│   │   ├── group
│   │   ├── hostname
│   │   ├── master.passwd
│   │   ├── motd
│   │   ├── msk.conf
│   │   ├── panel.menu
│   │   ├── passwd
│   │   ├── startup.d/
│   │   │   ├── 00_startuplog.sh
│   │   │   ├── 01_migrate.sh
│   │   │   ├── 02_hostname.sh
│   │   │   ├── 03_tmpfs.sh
│   │   │   ├── 04_modprobe.sh
│   │   │   ├── 05_mountcd.sh
│   │   │   ├── 40_dhcp.sh
│   │   │   ├── 50_msk.sh
│   │   │   └── 99_runstart.sh
│   │   ├── sudoers
│   │   └── weather.json
│   ├── home/
│   │   ├── guest/
│   │   │   └── hello
│   │   ├── local/
│   │   │   ├── .bim3rc
│   │   │   ├── .eshrc
│   │   │   ├── .wallpaper.conf
│   │   │   ├── .yutanirc
│   │   │   ├── Desktop/
│   │   │   │   ├── 0_file_browser.launcher
│   │   │   │   ├── 1_terminal.launcher
│   │   │   │   ├── 2_packages.launcher
│   │   │   │   └── 3_read_me.launcher
│   │   │   ├── README.md
│   │   │   └── text_layout.krk
│   │   └── root/
│   │       ├── .bimrc
│   │       └── hello
│   ├── lib/
│   │   └── .dummy
│   └── usr/
│       ├── include/
│       │   ├── _cheader.h
│       │   ├── alloca.h
│       │   ├── arpa/
│       │   │   └── inet.h
│       │   ├── assert.h
│       │   ├── bits/
│       │   │   ├── dirent.h
│       │   │   └── timespec.h
│       │   ├── ctype.h
│       │   ├── dirent.h
│       │   ├── dlfcn.h
│       │   ├── errno.h
│       │   ├── fcntl.h
│       │   ├── getopt.h
│       │   ├── iconv.h
│       │   ├── inttypes.h
│       │   ├── kernel/
│       │   │   ├── arch/
│       │   │   │   ├── aarch64/
│       │   │   │   │   ├── dtb.h
│       │   │   │   │   ├── gic.h
│       │   │   │   │   ├── pml.h
│       │   │   │   │   ├── regs.h
│       │   │   │   │   └── rpi.h
│       │   │   │   └── x86_64/
│       │   │   │       ├── acpi.h
│       │   │   │       ├── cmos.h
│       │   │   │       ├── irq.h
│       │   │   │       ├── pml.h
│       │   │   │       ├── ports.h
│       │   │   │       └── regs.h
│       │   │   ├── args.h
│       │   │   ├── assert.h
│       │   │   ├── elf.h
│       │   │   ├── generic.h
│       │   │   ├── gzip.h
│       │   │   ├── hashmap.h
│       │   │   ├── ksym.h
│       │   │   ├── list.h
│       │   │   ├── misc.h
│       │   │   ├── mmu.h
│       │   │   ├── mod/
│       │   │   │   ├── rtl.h
│       │   │   │   ├── shell.h
│       │   │   │   ├── snd.h
│       │   │   │   └── sound.h
│       │   │   ├── module.h
│       │   │   ├── mouse.h
│       │   │   ├── multiboot.h
│       │   │   ├── mutex.h
│       │   │   ├── net/
│       │   │   │   ├── e1000.h
│       │   │   │   ├── eth.h
│       │   │   │   ├── ipv4.h
│       │   │   │   └── netif.h
│       │   │   ├── pci.h
│       │   │   ├── pipe.h
│       │   │   ├── printf.h
│       │   │   ├── process.h
│       │   │   ├── procfs.h
│       │   │   ├── ptrace.h
│       │   │   ├── pty.h
│       │   │   ├── ramdisk.h
│       │   │   ├── ringbuffer.h
│       │   │   ├── shm.h
│       │   │   ├── signal.h
│       │   │   ├── spinlock.h
│       │   │   ├── string.h
│       │   │   ├── symboltable.h
│       │   │   ├── syscall.h
│       │   │   ├── time.h
│       │   │   ├── tmpfs.h
│       │   │   ├── tokenize.h
│       │   │   ├── tree.h
│       │   │   ├── types.h
│       │   │   ├── version.h
│       │   │   ├── vfs.h
│       │   │   └── video.h
│       │   ├── libgen.h
│       │   ├── libintl.h
│       │   ├── limits.h
│       │   ├── locale.h
│       │   ├── math.h
│       │   ├── memory.h
│       │   ├── net/
│       │   │   └── if.h
│       │   ├── netdb.h
│       │   ├── netinet/
│       │   │   └── in.h
│       │   ├── poll.h
│       │   ├── pthread.h
│       │   ├── pty.h
│       │   ├── pwd.h
│       │   ├── sched.h
│       │   ├── setjmp.h
│       │   ├── signal.h
│       │   ├── stdint.h
│       │   ├── stdio.h
│       │   ├── stdlib.h
│       │   ├── string.h
│       │   ├── strings.h
│       │   ├── sys/
│       │   │   ├── fswait.h
│       │   │   ├── ioctl.h
│       │   │   ├── mman.h
│       │   │   ├── mount.h
│       │   │   ├── param.h
│       │   │   ├── ptrace.h
│       │   │   ├── shm.h
│       │   │   ├── signal.h
│       │   │   ├── signal_defs.h
│       │   │   ├── socket.h
│       │   │   ├── stat.h
│       │   │   ├── sysfunc.h
│       │   │   ├── termios.h
│       │   │   ├── time.h
│       │   │   ├── times.h
│       │   │   ├── types.h
│       │   │   ├── uregs.h
│       │   │   ├── utsname.h
│       │   │   └── wait.h
│       │   ├── syscall.h
│       │   ├── syscall_nums.h
│       │   ├── termio.h
│       │   ├── termios.h
│       │   ├── time.h
│       │   ├── toaru/
│       │   │   ├── auth.h
│       │   │   ├── button.h
│       │   │   ├── confreader.h
│       │   │   ├── decodeutf8.h
│       │   │   ├── decorations.h
│       │   │   ├── drawstring.h
│       │   │   ├── graphics.h
│       │   │   ├── hashmap.h
│       │   │   ├── icon_cache.h
│       │   │   ├── inflate.h
│       │   │   ├── jpeg.h
│       │   │   ├── json.h
│       │   │   ├── kbd.h
│       │   │   ├── list.h
│       │   │   ├── markup.h
│       │   │   ├── markup_text.h
│       │   │   ├── menu.h
│       │   │   ├── mouse.h
│       │   │   ├── panel.h
│       │   │   ├── pex.h
│       │   │   ├── png.h
│       │   │   ├── rline.h
│       │   │   ├── spinlock.h
│       │   │   ├── termemu.h
│       │   │   ├── text.h
│       │   │   ├── trace.h
│       │   │   ├── tree.h
│       │   │   ├── yutani-internal.h
│       │   │   ├── yutani-server.h
│       │   │   └── yutani.h
│       │   ├── unistd.h
│       │   ├── utime.h
│       │   ├── va_list.h
│       │   ├── wait.h
│       │   └── wchar.h
│       └── share/
│           ├── bim/
│           │   ├── site/
│           │   │   └── __init__.krk
│           │   ├── syntax/
│           │   │   ├── __init__.krk
│           │   │   ├── bash.krk
│           │   │   ├── biminfo.krk
│           │   │   ├── c.krk
│           │   │   ├── conf.krk
│           │   │   ├── css.krk
│           │   │   ├── ctags.krk
│           │   │   ├── diff.krk
│           │   │   ├── dirent.krk
│           │   │   ├── dlang.krk
│           │   │   ├── docker.krk
│           │   │   ├── doxygen.krk
│           │   │   ├── esh.krk
│           │   │   ├── gas.krk
│           │   │   ├── git.krk
│           │   │   ├── graphql.krk
│           │   │   ├── groovy.krk
│           │   │   ├── hosts.krk
│           │   │   ├── issue.krk
│           │   │   ├── java.krk
│           │   │   ├── javascript.krk
│           │   │   ├── json.krk
│           │   │   ├── krk.krk
│           │   │   ├── latex.krk
│           │   │   ├── ld.krk
│           │   │   ├── lisp.krk
│           │   │   ├── lua.krk
│           │   │   ├── make.krk
│           │   │   ├── man.krk
│           │   │   ├── markdown.krk
│           │   │   ├── protobuf.krk
│           │   │   ├── py.krk
│           │   │   ├── rust.krk
│           │   │   └── xml.krk
│           │   └── themes/
│           │       ├── __init__.krk
│           │       ├── ansi.krk
│           │       ├── citylights.krk
│           │       ├── light.krk
│           │       ├── solarized.krk
│           │       ├── strawberry.krk
│           │       ├── sunsmoke.krk
│           │       ├── tiff.krk
│           │       └── wombat.krk
│           └── help/
│               ├── 0_index.trt
│               ├── calculator.trt
│               ├── file-browser.trt
│               ├── help-browser.trt
│               ├── package-manager.trt
│               └── terminal.trt
├── boot/
│   ├── README.md
│   ├── boot.S
│   ├── config.c
│   ├── editor.c
│   ├── editor.h
│   ├── elf.h
│   ├── iso9660.h
│   ├── kbd.c
│   ├── kbd.h
│   ├── link.ld
│   ├── mbr.S
│   ├── menu.c
│   ├── menu.h
│   ├── multiboot.c
│   ├── multiboot.h
│   ├── options.h
│   ├── platform.c
│   ├── qemu.c
│   ├── qemu.h
│   ├── text.c
│   ├── text.h
│   ├── util.c
│   ├── util.h
│   └── video.c
├── build/
│   ├── aarch64.mk
│   └── x86_64.mk
├── kernel/
│   ├── arch/
│   │   ├── aarch64/
│   │   │   ├── arch.c
│   │   │   ├── bootstub/
│   │   │   │   ├── bootstrap.S
│   │   │   │   ├── link.ld
│   │   │   │   └── main.c
│   │   │   ├── context.S
│   │   │   ├── dtb.c
│   │   │   ├── entry.S
│   │   │   ├── fwcfg.c
│   │   │   ├── gic.c
│   │   │   ├── irq.S
│   │   │   ├── link.ld
│   │   │   ├── main.c
│   │   │   ├── mmu.c
│   │   │   ├── pl011.c
│   │   │   ├── rpi.c
│   │   │   ├── rpi400/
│   │   │   │   ├── fbterm.c
│   │   │   │   ├── link.ld
│   │   │   │   ├── main.c
│   │   │   │   └── start.S
│   │   │   ├── rpi_miniuart.c
│   │   │   ├── smp.c
│   │   │   ├── traceback.c
│   │   │   └── virtio.c
│   │   └── x86_64/
│   │       ├── bootstrap.S
│   │       ├── cmos.c
│   │       ├── gdt.c
│   │       ├── idt.c
│   │       ├── irq.S
│   │       ├── link.ld
│   │       ├── main.c
│   │       ├── mmu.c
│   │       ├── pic.c
│   │       ├── pit.c
│   │       ├── ports.c
│   │       ├── ps2hid.c
│   │       ├── serial.c
│   │       ├── smp.c
│   │       └── user.c
│   ├── audio/
│   │   └── snd.c
│   ├── binfmt.c
│   ├── generic.c
│   ├── misc/
│   │   ├── args.c
│   │   ├── assert.c
│   │   ├── elf64.c
│   │   ├── fbterm.c
│   │   ├── gzip.c
│   │   ├── hashmap.c
│   │   ├── kprintf.c
│   │   ├── ksym.c
│   │   ├── list.c
│   │   ├── malloc.c
│   │   ├── pci.c
│   │   ├── ringbuffer.c
│   │   ├── string.c
│   │   ├── tokenize.c
│   │   └── tree.c
│   ├── net/
│   │   ├── arp.c
│   │   ├── eth.c
│   │   ├── ipv4.c
│   │   ├── loop.c
│   │   ├── netif.c
│   │   └── socket.c
│   ├── sys/
│   │   ├── mutex.c
│   │   ├── process.c
│   │   ├── ptrace.c
│   │   ├── shm.c
│   │   ├── signal.c
│   │   ├── syscall.c
│   │   └── version.c
│   ├── vfs/
│   │   ├── console.c
│   │   ├── packetfs.c
│   │   ├── pipe.c
│   │   ├── portio.c
│   │   ├── procfs.c
│   │   ├── ramdisk.c
│   │   ├── random.c
│   │   ├── tarfs.c
│   │   ├── tmpfs.c
│   │   ├── tty.c
│   │   ├── unixpipe.c
│   │   ├── vfs.c
│   │   └── zero.c
│   └── video/
│       └── lfbvideo.c
├── lib/
│   ├── README.md
│   ├── auth.c
│   ├── button.c
│   ├── confreader.c
│   ├── decor-fancy.c
│   ├── decorations.c
│   ├── graphics.c
│   ├── hashmap.c
│   ├── icon_cache.c
│   ├── inflate.c
│   ├── jpeg.c
│   ├── json.c
│   ├── kbd.c
│   ├── kuroko/
│   │   ├── _waitpid.c
│   │   ├── _yutani2.c
│   │   └── yutani_mainloop.krk
│   ├── list.c
│   ├── markup.c
│   ├── markup_text.c
│   ├── menu.c
│   ├── panel_appmenu.c
│   ├── panel_clock.c
│   ├── panel_date.c
│   ├── panel_logout.c
│   ├── panel_network.c
│   ├── panel_volume.c
│   ├── panel_weather.c
│   ├── panel_windowlist.c
│   ├── pex.c
│   ├── png.c
│   ├── rline.c
│   ├── rline_exp.c
│   ├── termemu.c
│   ├── text.c
│   ├── tree.c
│   └── yutani.c
├── libc/
│   ├── arch/
│   │   ├── aarch64/
│   │   │   ├── bad.c
│   │   │   ├── crt0.S
│   │   │   ├── crti.S
│   │   │   ├── crtn.S
│   │   │   ├── memcpy.c
│   │   │   ├── memset.c
│   │   │   └── setjmp.c
│   │   └── x86_64/
│   │       ├── crt0.S
│   │       ├── crti.S
│   │       ├── crtn.S
│   │       ├── math.c
│   │       ├── memcpy.c
│   │       ├── memset.c
│   │       └── setjmp.c
│   ├── assert/
│   │   └── assert.c
│   ├── ctype/
│   │   ├── _ctype.c
│   │   ├── isalnum.c
│   │   ├── isalpha.c
│   │   ├── isascii.c
│   │   ├── iscntrl.c
│   │   ├── isdigit.c
│   │   ├── isgraph.c
│   │   ├── islower.c
│   │   ├── isprint.c
│   │   ├── ispunct.c
│   │   ├── isspace.c
│   │   ├── isupper.c
│   │   ├── isxdigit.c
│   │   ├── tolower.c
│   │   └── toupper.c
│   ├── dirent/
│   │   ├── dir.c
│   │   └── mkdir.c
│   ├── dlfcn/
│   │   └── dlfcn.c
│   ├── errno/
│   │   └── errorno.c
│   ├── iconv/
│   │   └── iconv.c
│   ├── ioctl/
│   │   └── ioctl.c
│   ├── libgen/
│   │   ├── basename.c
│   │   └── dirname.c
│   ├── libintl/
│   │   └── libintl.c
│   ├── locale/
│   │   ├── localeconv.c
│   │   └── setlocale.c
│   ├── main.c
│   ├── math/
│   │   ├── bad.c
│   │   └── math.c
│   ├── poll/
│   │   └── poll.c
│   ├── pthread/
│   │   ├── pthread.c
│   │   └── pthread_rwlock.c
│   ├── pty/
│   │   └── pty.c
│   ├── pwd/
│   │   └── pwd.c
│   ├── sched/
│   │   └── sched_yield.c
│   ├── signal/
│   │   ├── kill.c
│   │   ├── raise.c
│   │   ├── sigaction.c
│   │   ├── signal.c
│   │   ├── sigpending.c
│   │   ├── sigprocmask.c
│   │   ├── sigset.c
│   │   └── sigsuspend.c
│   ├── stdio/
│   │   ├── perror.c
│   │   ├── printf.c
│   │   ├── puts.c
│   │   ├── remove.c
│   │   ├── rename.c
│   │   ├── scanf.c
│   │   ├── stdio.c
│   │   ├── tmpfile.c
│   │   └── tmpnam.c
│   ├── stdlib/
│   │   ├── abort.c
│   │   ├── atexit.c
│   │   ├── atof.c
│   │   ├── bsearch.c
│   │   ├── div.c
│   │   ├── getenv.c
│   │   ├── labs.c
│   │   ├── malloc.c
│   │   ├── mbstowcs.c
│   │   ├── mktemp.c
│   │   ├── putenv.c
│   │   ├── qsort.c
│   │   ├── rand.c
│   │   ├── realpath.c
│   │   ├── setenv.c
│   │   ├── strtod.c
│   │   ├── strtoul.c
│   │   └── system.c
│   ├── string/
│   │   ├── memmove.c
│   │   ├── str.c
│   │   ├── strerror.c
│   │   ├── strncmp.c
│   │   ├── strncpy.c
│   │   ├── strsignal.c
│   │   └── strxfrm.c
│   ├── strings/
│   │   └── strcasecmp.c
│   ├── sys/
│   │   ├── fswait.c
│   │   ├── mount.c
│   │   ├── network.c
│   │   ├── ptrace.c
│   │   ├── reboot.c
│   │   ├── shm.c
│   │   ├── sysfunc.c
│   │   ├── uname.c
│   │   └── wait.c
│   ├── time/
│   │   ├── clock.c
│   │   ├── clock_gettime.c
│   │   ├── ctime.c
│   │   ├── gettimeofday.c
│   │   ├── localtime.c
│   │   ├── settimeofday.c
│   │   ├── strftime.c
│   │   ├── time.c
│   │   └── times.c
│   ├── unistd/
│   │   ├── access.c
│   │   ├── alarm.c
│   │   ├── chdir.c
│   │   ├── chmod.c
│   │   ├── chown.c
│   │   ├── close.c
│   │   ├── creat.c
│   │   ├── dup2.c
│   │   ├── execvp.c
│   │   ├── exit.c
│   │   ├── fcntl.c
│   │   ├── fork.c
│   │   ├── fstat.c
│   │   ├── getcwd.c
│   │   ├── getegid.c
│   │   ├── geteuid.c
│   │   ├── getgid.c
│   │   ├── getgroups.c
│   │   ├── getlogin.c
│   │   ├── getopt.c
│   │   ├── getopt_long.c
│   │   ├── getpgrp.c
│   │   ├── getpid.c
│   │   ├── getuid.c
│   │   ├── getwd.c
│   │   ├── hostname.c
│   │   ├── isatty.c
│   │   ├── link.c
│   │   ├── lseek.c
│   │   ├── open.c
│   │   ├── pathconf.c
│   │   ├── pipe.c
│   │   ├── pread.c
│   │   ├── pwrite.c
│   │   ├── read.c
│   │   ├── readlink.c
│   │   ├── rmdir.c
│   │   ├── sbrk.c
│   │   ├── setgid.c
│   │   ├── setgroups.c
│   │   ├── setpgid.c
│   │   ├── setsid.c
│   │   ├── setuid.c
│   │   ├── sleep.c
│   │   ├── stat.c
│   │   ├── statcompat.c
│   │   ├── symlink.c
│   │   ├── sync.c
│   │   ├── truncate.c
│   │   ├── ttyname.c
│   │   ├── umask.c
│   │   ├── unlink.c
│   │   ├── usleep.c
│   │   └── write.c
│   ├── utime/
│   │   └── utime.c
│   └── wchar/
│       ├── wcscat.c
│       ├── wcscmp.c
│       ├── wcscpy.c
│       ├── wcslen.c
│       ├── wcsncpy.c
│       ├── wcstok.c
│       ├── wcstol.c
│       └── wcwidth.c
├── linker/
│   ├── README.md
│   ├── link.ld
│   └── linker.c
├── modules/
│   ├── ac97.c
│   ├── ahci.c
│   ├── ata.c
│   ├── dospart.c
│   ├── e1000.c
│   ├── es1371.c
│   ├── ext2.c
│   ├── hda.c
│   ├── i965.c
│   ├── iso9660.c
│   ├── pcspkr.c
│   ├── piix4.c
│   ├── test.c
│   ├── vbox.c
│   ├── vmware.c
│   └── xhci.c
└── util/
    ├── __init__.krk
    ├── activate.sh
    ├── arch.sh
    ├── auto-dep.krk
    ├── bochsrc.txt
    ├── build-in-docker-aarch64.sh
    ├── build-in-docker.sh
    ├── build-toolchain.sh
    ├── createramdisk.py
    ├── docker/
    │   ├── Dockerfile
    │   └── README.md
    ├── gen_wcwidth.krk
    ├── generate-etc-issue.sh
    ├── generate-etc-os-release.sh
    ├── generate-release-notes.sh
    ├── gensym.krk
    ├── init.krk
    ├── libm.c
    ├── make-version
    ├── make_mbr.krk
    ├── mkdisk.sh
    ├── update-extents.krk
    └── valid-modules.sh
Download .txt
Showing preview only (400K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (5110 symbols across 532 files)

FILE: apps/about.c
  function center_x (line 36) | static int center_x(int x) {
  function draw_string (line 40) | static void draw_string(int y, const char * string, int mode, uint32_t c...
  function redraw (line 56) | static void redraw(void) {
  function init_default (line 87) | static void init_default(void) {
  function resize_finish (line 111) | void resize_finish(int w, int h) {
  function main (line 122) | int main(int argc, char * argv[]) {

FILE: apps/basename.c
  function main (line 13) | int main(int argc, char * argv[]) {

FILE: apps/beep.c
  type spkr (line 20) | struct spkr {
  function note (line 25) | static void note(int length, int frequency) {
  function beep (line 45) | void beep(void) {
  function main (line 55) | int main(int argc, char * argv[]) {

FILE: apps/bim.c
  type key_name_map (line 95) | struct key_name_map
  type Key (line 121) | enum Key
  type SyntaxState (line 141) | struct SyntaxState {
  type ColorName (line 186) | struct ColorName
  type action_def (line 236) | struct action_def
  type command_def (line 237) | struct command_def
  type command_def (line 238) | struct command_def
  type theme_def (line 239) | struct theme_def
  function bim_unget (line 246) | void bim_unget(int c) {
  function bim_getch_timeout (line 251) | int bim_getch_timeout(int timeout) {
  function decode (line 293) | static inline uint32_t decode(uint32_t* state, uint32_t* codep, unsigned...
  function _shift_key (line 332) | int _shift_key(int i, int this_buf[20], int *timeout) {
  function bim_getkey (line 345) | int bim_getkey(int read_timeout) {
  function key_from_name (line 469) | enum Key key_from_name(const char * name) {
  function buffer_t (line 517) | buffer_t * buffer_new(void) {
  function FILE (line 551) | FILE * open_biminfo(void) {
  function file_is_open (line 576) | int file_is_open(char * file) {
  function fetch_from_biminfo (line 639) | int fetch_from_biminfo(buffer_t * buf) {
  function update_biminfo (line 697) | int update_biminfo(buffer_t * buf, int is_open) {
  function cancel_background_tasks (line 759) | void cancel_background_tasks(buffer_t * buf) {
  function buffer_t (line 785) | buffer_t * buffer_close(buffer_t * buf) {
  function match_and_paint (line 890) | static int match_and_paint(struct syntax_state * state, const char * key...
  function simple_keyword_qualifier (line 914) | static int simple_keyword_qualifier(int c) {
  function common_comment_buzzwords (line 923) | static int common_comment_buzzwords(struct syntax_state * state) {
  function paint_comment (line 935) | static int paint_comment(struct syntax_state * state) {
  type syntax_definition (line 946) | struct syntax_definition
  type syntax_definition (line 947) | struct syntax_definition
  type syntax_definition (line 957) | struct syntax_definition
  function add_syntax (line 959) | void add_syntax(struct syntax_definition def) {
  function recalculate_syntax (line 992) | void recalculate_syntax(line_t * line, int line_no) {
  function recalculate_tabs (line 1070) | void recalculate_tabs(line_t * line) {
  function history_free (line 1103) | void history_free(history_t * root) {
  function set_history_break (line 1156) | void set_history_break(void) {
  function line_t (line 1178) | __attribute__((warn_unused_result)) line_t * line_insert(line_t * line, ...
  function line_delete (line 1227) | void line_delete(line_t * line, int offset, int lineno) {
  function line_replace (line 1264) | void line_replace(line_t * line, char_t _c, int offset, int lineno) {
  function line_t (line 1295) | line_t ** remove_line(line_t ** lines, int offset) {
  function line_t (line 1337) | line_t ** add_line(line_t ** lines, int offset) {
  function replace_line (line 1385) | void replace_line(line_t ** lines, int offset, line_t * replacement) {
  function line_t (line 1421) | line_t ** merge_lines(line_t ** lines, int lineb) {
  function line_t (line 1480) | line_t ** split_line(line_t ** lines, int line, int split) {
  function line_ends_with_brace (line 1564) | int line_ends_with_brace(line_t * line) {
  function line_is_comment (line 1584) | int line_is_comment(line_t * line) {
  function find_brace_line_start (line 1606) | int find_brace_line_start(int line, int col) {
  function add_indent (line 1640) | void add_indent(int new_line, int old_line, int ignore_brace) {
  function setup_buffer (line 1743) | void setup_buffer(buffer_t * env) {
  type termios (line 1778) | struct termios
  function get_initial_termios (line 1779) | void get_initial_termios(void) {
  function set_unbuffered (line 1783) | void set_unbuffered(void) {
  function set_buffered (line 1796) | void set_buffered(void) {
  function to_eight (line 1803) | int to_eight(uint32_t codepoint, char * out) {
  function codepoint_width (line 1841) | int codepoint_width(wchar_t codepoint) {
  function place_cursor (line 1884) | void place_cursor(int x, int y) {
  function set_colors (line 1929) | void set_colors(const char * fg, const char * bg) {
  function set_fg_color (line 1938) | void set_fg_color(const char * fg) {
  function clear_to_end (line 1955) | void clear_to_end(void) {
  function paint_line (line 1965) | void paint_line(const char * bg) {
  function set_bold (line 1978) | void set_bold(void) {
  function unset_bold (line 1985) | void unset_bold(void) {
  function set_underline (line 1992) | void set_underline(void) {
  function unset_underline (line 1999) | void unset_underline(void) {
  function reset (line 2006) | void reset(void) {
  function clear_screen (line 2013) | void clear_screen(void) {
  function hide_cursor (line 2020) | void hide_cursor(void) {
  function show_cursor (line 2029) | void show_cursor(void) {
  function store_cursor (line 2038) | void store_cursor(void) {
  function restore_cursor (line 2045) | void restore_cursor(void) {
  function mouse_enable (line 2052) | void mouse_enable(void) {
  function mouse_disable (line 2064) | void mouse_disable(void) {
  function shift_up (line 2076) | void shift_up(int amount) {
  function shift_down (line 2083) | void shift_down(int amount) {
  function insert_lines_at (line 2087) | void insert_lines_at(int line, int count) {
  function delete_lines_at (line 2092) | void delete_lines_at(int line, int count) {
  function set_alternate_screen (line 2100) | void set_alternate_screen(void) {
  function unset_alternate_screen (line 2109) | void unset_alternate_screen(void) {
  function set_bracketed_paste (line 2118) | void set_bracketed_paste(void) {
  function unset_bracketed_paste (line 2127) | void unset_bracketed_paste(void) {
  function draw_tab_name (line 2151) | int draw_tab_name(buffer_t * _env, char * out, int max_width, int * widt...
  function redraw_tabbar (line 2218) | void redraw_tabbar(void) {
  function log_base_10 (line 2298) | int log_base_10(unsigned int v) {
  function render_line (line 2316) | void render_line(line_t * line, int width, int offset, int line_no) {
  function num_width (line 2606) | int num_width(void) {
  function gutter_width (line 2616) | int gutter_width(void) {
  function draw_line_number (line 2623) | void draw_line_number(int x) {
  function recalculate_current_line (line 2645) | void recalculate_current_line(void) {
  function redraw_line (line 2676) | void redraw_line(int x) {
  function draw_excess_line (line 2743) | void draw_excess_line(int j) {
  function redraw_text (line 2761) | void redraw_text(void) {
  function redraw_alt_buffer (line 2792) | void redraw_alt_buffer(buffer_t * buf) {
  function display_width_of_string (line 2831) | int display_width_of_string(const char * str) {
  function statusbar_append_status (line 2848) | void statusbar_append_status(int *remaining_width, size_t *filled, char ...
  function statusbar_build_right (line 2879) | int statusbar_build_right(char * right_hand) {
  function redraw_statusbar (line 2905) | void redraw_statusbar(void) {
  function redraw_nav_buffer (line 3008) | void redraw_nav_buffer(void) {
  function redraw_commandline (line 3025) | void redraw_commandline(void) {
  function render_commandline_message (line 3096) | void render_commandline_message(char * message, ...) {
  function pause_for_key (line 3138) | void pause_for_key(void) {
  function redraw_most (line 3148) | void redraw_most(void) {
  function unsplit (line 3158) | void unsplit(void) {
  function update_title (line 3176) | void update_title(void) {
  function set_modified (line 3191) | void set_modified(void) {
  function render_status_message (line 3207) | void render_status_message(char * message, ...) {
  function render_error (line 3234) | void render_error(char * message, ...) {
  function is_paren (line 3262) | int is_paren(int c) {
  function highlight_matching_paren (line 3291) | void highlight_matching_paren(void) {
  function unhighlight_matching_paren (line 3317) | void unhighlight_matching_paren(void) {
  function place_cursor_actual (line 3335) | void place_cursor_actual(void) {
  function update_split_size (line 3406) | void update_split_size(void) {
  function update_screen_size (line 3426) | void update_screen_size(void) {
  function SIGWINCH_handler (line 3448) | void SIGWINCH_handler(int sig) {
  function SIGTSTP_handler (line 3459) | void SIGTSTP_handler(int sig) {
  function SIGCONT_handler (line 3474) | void SIGCONT_handler(int sig) {
  function SIGINT_handler (line 3487) | void SIGINT_handler(int sig) {
  function try_to_center (line 3492) | void try_to_center(void) {
  function add_buffer (line 3541) | void add_buffer(uint8_t * buf, int size) {
  function add_string (line 3577) | void add_string(char * string) {
  function str_ends_with (line 3581) | int str_ends_with(const char * haystack, const char * needle) {
  type syntax_definition (line 3597) | struct syntax_definition
  type syntax_definition (line 3598) | struct syntax_definition
  function set_syntax_by_name (line 3610) | void set_syntax_by_name(const char * name) {
  function is_all_numbers (line 3640) | int is_all_numbers(const char * c) {
  type file_listing (line 3648) | struct file_listing {
  function sort_files (line 3653) | int sort_files(const void * a, const void * b) {
  function read_directory_into_buffer (line 3664) | void read_directory_into_buffer(char * file) {
  function line_matches (line 3756) | int line_matches(line_t * line, char * string) {
  function run_onload (line 3772) | void run_onload(buffer_t * env) {
  function render_syntax_async (line 3815) | static void render_syntax_async(background_task_t * task) {
  function schedule_complete_recalc (line 3832) | static void schedule_complete_recalc(void) {
  function open_file (line 3861) | void open_file(char * file) {
  function quit (line 4060) | void quit(const char * message) {
  function try_quit (line 4079) | void try_quit(void) {
  function git_examine (line 4158) | int git_examine(char * filename) {
  function output_file (line 4256) | void output_file(buffer_t * env, FILE * f) {
  function write_file (line 4280) | void write_file(char * file) {
  function close_buffer (line 4331) | void close_buffer(void) {
  function set_preferred_column (line 4369) | void set_preferred_column(void) {
  type MatchQualifier (line 4631) | struct MatchQualifier {
  function match_char (line 4645) | int match_char(struct MatchQualifier * self, uint32_t b, int mode) {
  function match_squares (line 4654) | int match_squares(struct MatchQualifier * self, uint32_t c, int mode) {
  function match_dot (line 4685) | int match_dot(struct MatchQualifier * self, uint32_t c, int mode) {
  type BackRef (line 4689) | struct BackRef {
  function regex_matches (line 4696) | int regex_matches(line_t * line, int j, uint32_t * needle, int ignorecas...
  function subsearch_matches (line 4813) | int subsearch_matches(line_t * line, int j, uint32_t * needle, int ignor...
  function perform_replacement (line 4820) | void perform_replacement(int line_no, uint32_t * needle, uint32_t * repl...
  function insert_command_history (line 4908) | void insert_command_history(unsigned char ** which_history, char * cmd) {
  function html_convert_color (line 4957) | static void html_convert_color(const char * color_string) {
  function convert_to_html (line 4999) | int convert_to_html(void) {
  function _prefix_command_run_script (line 5202) | int _prefix_command_run_script(char * cmd) {
  function replace_text (line 5313) | int replace_text(int range_top, int range_bot, char divider, char * need...
  type command_def (line 5737) | struct command_def
  type command_def (line 5746) | struct command_def
  type theme_def (line 5777) | struct theme_def
  function isSubstitutionSymbol (line 6095) | int isSubstitutionSymbol(int c) {
  function alldigits (line 6103) | int alldigits(const char * c) {
  function process_command (line 6115) | int process_command(char * cmd) {
  type Candidate (line 6165) | struct Candidate {
  function biased_strcmp (line 6170) | static int biased_strcmp(const char *l, const char *r) {
  function compare_candidate (line 6181) | int compare_candidate(const void * a, const void * b) {
  function KrkValue (line 6196) | static KrkValue findFromProperty(KrkValue current, KrkToken next) {
  function command_buffer_clear_before (line 6219) | static void command_buffer_clear_before(void) {
  type StringBuilder (line 6233) | struct StringBuilder
  function command_buffer_deserialize (line 6250) | static void command_buffer_deserialize(char * tmp) {
  type Candidate (line 6289) | struct Candidate
  type Candidate (line 6289) | struct Candidate
  type command_def (line 6339) | struct command_def
  type command_def (line 6342) | struct command_def
  type syntax_definition (line 6352) | struct syntax_definition
  type theme_def (line 6360) | struct theme_def
  type ColorName (line 6367) | struct ColorName
  type action_def (line 6374) | struct action_def
  type mode_names (line 6395) | struct mode_names
  type action_def (line 6403) | struct action_def
  type dirent (line 6455) | struct dirent
  type stat (line 6458) | struct stat
  type StringBuilder (line 6669) | struct StringBuilder
  type StringBuilder (line 6683) | struct StringBuilder
  type StringBuilder (line 6706) | struct StringBuilder
  type StringBuilder (line 6788) | struct StringBuilder
  function render_command_input_buffer (line 6853) | void render_command_input_buffer(void) {
  function _restore_history (line 7048) | static void _restore_history(unsigned char **which_history, int point) {
  function _scroll_history (line 7066) | static void _scroll_history(int direction, unsigned char **which_history...
  function smart_case (line 7174) | int smart_case(uint32_t * str) {
  function find_match (line 7191) | void find_match(int from_line, int from_col, int * out_line, int * out_c...
  function find_match_backwards (line 7215) | void find_match_backwards(int from_line, int from_col, int * out_line, i...
  function rehighlight_search (line 7243) | void rehighlight_search(line_t * line) {
  function draw_search_match (line 7266) | void draw_search_match(uint32_t * buffer, int redraw_buffer) {
  function find_matching_paren (line 7496) | void find_matching_paren(int * out_line, int * out_col, int in_col) {
  function handle_common_mouse (line 7591) | void handle_common_mouse(int buttons, int x, int y) {
  function is_whitespace (line 8105) | int is_whitespace(int codepoint) {
  function is_normal (line 8109) | int is_normal(int codepoint) {
  function is_special (line 8113) | int is_special(int codepoint) {
  function yank_partial_line (line 8399) | void yank_partial_line(int yank_no, int line_no, int start_off, int coun...
  function yank_text (line 8421) | void yank_text(int start_line, int start_col, int end_line, int end_col) {
  function realign_column_cursor (line 8493) | void realign_column_cursor(void) {
  function reset_nav_buffer (line 8622) | void reset_nav_buffer(int c) {
  function point_in_range (line 8637) | int point_in_range(int start_line, int end_line, int start_col, int end_...
  function recalculate_selected_lines (line 8798) | void recalculate_selected_lines(void) {
  function free_completion_match (line 9170) | void free_completion_match(struct completion_match * match) {
  function read_tags (line 9179) | int read_tags(uint32_t * comp, struct completion_match **matches, int * ...
  function draw_completion_matches (line 9222) | void draw_completion_matches(uint32_t * tmp, struct completion_match *ma...
  function omni_complete (line 9290) | int omni_complete(int quit_quietly_on_none) {
  function set_search_from_bytes (line 9404) | static void set_search_from_bytes(char * bytes) {
  function _perform_correct_search (line 9429) | static void _perform_correct_search(struct completion_match * matches, i...
  type completion_match (line 9447) | struct completion_match
  function read_one_character (line 9501) | int read_one_character(char * message) {
  function read_one_byte (line 9526) | int read_one_byte(char * message) {
  type action_map (line 9980) | struct action_map
  type action_map (line 10008) | struct action_map
  type action_map (line 10025) | struct action_map
  type action_map (line 10033) | struct action_map
  type action_map (line 10053) | struct action_map
  type action_map (line 10069) | struct action_map
  type action_map (line 10079) | struct action_map
  type action_map (line 10095) | struct action_map
  type action_map (line 10136) | struct action_map
  type action_map (line 10169) | struct action_map
  type action_map (line 10178) | struct action_map
  type action_map (line 10187) | struct action_map
  type action_map (line 10196) | struct action_map
  type action_map (line 10216) | struct action_map
  type action_map (line 10221) | struct action_map
  type action_map (line 10222) | struct action_map
  type action_map (line 10223) | struct action_map
  type action_map (line 10224) | struct action_map
  type action_map (line 10225) | struct action_map
  type action_map (line 10226) | struct action_map
  type action_map (line 10227) | struct action_map
  type action_map (line 10228) | struct action_map
  type action_map (line 10229) | struct action_map
  type action_map (line 10230) | struct action_map
  type action_map (line 10231) | struct action_map
  type action_map (line 10232) | struct action_map
  type action_map (line 10233) | struct action_map
  type mode_names (line 10235) | struct mode_names
  function handle_action (line 10256) | int handle_action(struct action_map * basemap, int key) {
  function handle_nav_buffer (line 10319) | int handle_nav_buffer(int key) {
  function normal_mode (line 10340) | void normal_mode(void) {
  type CommandDef (line 10611) | struct CommandDef {
  function process_krk_command (line 10616) | int process_krk_command(const char * cmd, KrkValue * outVal) {
  function show_usage (line 10687) | static void show_usage(char * argv[]) {
  function set_capability (line 10732) | int set_capability(char * arg) {
  function load_bimrc (line 10803) | void load_bimrc(void) {
  function KRK_Function (line 10841) | KRK_Function(bindHighlighter) {
  function KRK_Function (line 10890) | KRK_Function(defineTheme) {
  function c_keyword_qualifier (line 10904) | static int c_keyword_qualifier(int c) {
  type StringBuilder (line 10958) | struct StringBuilder
  function callQualifier (line 11064) | static int callQualifier(KrkValue qualifier, int codepoint) {
  type SyntaxState (line 11159) | struct SyntaxState
  function KRK_Function (line 11165) | KRK_Function(getCommands) {
  type ActionDef (line 11178) | struct ActionDef {
  function import_directory (line 11249) | void import_directory(char * dirName) {
  function findBim (line 11348) | static void findBim(char * argv[]) {
  function do_kuroko_imports (line 11378) | static void do_kuroko_imports(void) {
  function KRK_Function (line 11410) | KRK_Function(getDocumentText) {
  function KRK_Function (line 11432) | KRK_Function(renderError) {
  function KRK_Function (line 11445) | KRK_Function(renderMessage) {
  function KRK_Function (line 11458) | KRK_Function(renderStatus) {
  function KRK_Function (line 11471) | KRK_Function(getDocumentFilename) {
  function KRK_Function (line 11477) | KRK_Function(bindkey) {
  function KRK_Function (line 11526) | KRK_Function(getkey) {
  function KRK_Function (line 11533) | KRK_Function(displayWidth) {
  function KRK_Function (line 11539) | KRK_Function(pauseForKey) {
  function KRK_Function (line 11544) | KRK_Function(paren_pairs) {
  function initialize (line 11579) | void initialize(void) {
  function init_terminal (line 11797) | void init_terminal(void) {
  type action_def (line 11815) | struct action_def
  function dump_mapping (line 11823) | void dump_mapping(const char * description, struct action_map * map) {
  function sort_regular_commands (line 11840) | int sort_regular_commands(const void * a, const void * b) {
  function sort_prefix_commands (line 11844) | int sort_prefix_commands(const void * a, const void * b) {
  function dump_commands (line 11848) | void dump_commands(void) {
  type MappingNames (line 11904) | struct MappingNames {
  type MappingNames (line 11926) | struct MappingNames
  type action_map (line 11928) | struct action_map
  type StringBuilder (line 11932) | struct StringBuilder
  type action_def (line 11938) | struct action_def
  type ColorName (line 11970) | struct ColorName
  type ColorName (line 11979) | struct ColorName
  type ColorName (line 11991) | struct ColorName
  function dump_map_commands (line 12082) | void dump_map_commands(const char * name, struct action_map * map) {
  type action_map (line 12139) | struct action_map
  type mode_names (line 12140) | struct mode_names
  type Key (line 12152) | enum Key
  type action_def (line 12158) | struct action_def
  type action_map (line 12206) | struct action_map
  type action_map (line 12207) | struct action_map
  type action_map (line 12217) | struct action_map
  type action_map (line 12218) | struct action_map
  function main (line 12239) | int main(int argc, char * argv[]) {

FILE: apps/bim.h
  type Key (line 48) | enum Key {
  type key_name_map (line 84) | struct key_name_map {
  type key_name_map (line 89) | struct key_name_map
  type char_t (line 126) | typedef struct {
  type line_t (line 137) | typedef struct {
  type background_task_t (line 146) | typedef struct background_task {
  type global_config_t (line 160) | typedef struct {
  type history_t (line 257) | typedef struct history {
  type buffer_t (line 292) | typedef struct _env {
  type theme_def (line 333) | struct theme_def {
  type theme_def (line 338) | struct theme_def
  type theme_def (line 340) | struct theme_def
  type syntax_state (line 342) | struct syntax_state {
  type completion_match (line 350) | struct completion_match {
  type syntax_definition (line 356) | struct syntax_definition {
  type syntax_definition (line 367) | struct syntax_definition
  type action_def (line 381) | struct action_def {
  type action_def (line 388) | struct action_def
  type command_def (line 402) | struct command_def {
  type Key (line 447) | enum Key
  type action_def (line 448) | struct action_def
  type command_def (line 451) | struct command_def
  type command_def (line 452) | struct command_def
  type syntax_definition (line 456) | struct syntax_definition
  type ColorName (line 458) | struct ColorName {
  type ColorName (line 463) | struct ColorName
  type bim_function (line 465) | struct bim_function {
  type bim_function (line 470) | struct bim_function
  type action_map (line 489) | struct action_map {
  type mode_names (line 510) | struct mode_names {
  type mode_names (line 516) | struct mode_names
  type syntax_state (line 527) | struct syntax_state
  type syntax_state (line 528) | struct syntax_state
  type syntax_state (line 529) | struct syntax_state
  type syntax_definition (line 530) | struct syntax_definition
  function _isdigit (line 533) | static __attribute__((used)) int _isdigit(int c) { if (c > 128) return 0...
  function _isxdigit (line 534) | static __attribute__((used)) int _isxdigit(int c) { if (c > 128) return ...

FILE: apps/block-dev-stats.c
  function main (line 18) | int main(int argc, char * argv[]) {

FILE: apps/cal.c
  function main (line 35) | int main(int argc, char * argv[]) {

FILE: apps/calculator.c
  type menu_bar (line 25) | struct menu_bar
  type menu_bar_entries (line 26) | struct menu_bar_entries
  type CalculatorButton (line 45) | struct CalculatorButton {
  function clear_result (line 51) | static void clear_result(void) {
  function calc_numeric (line 59) | static void calc_numeric(char * text) {
  function calc_func (line 64) | static void calc_func(char * txt) {
  function calc_backspace (line 72) | static void calc_backspace(void) {
  function btn_numeric (line 88) | static void btn_numeric(struct CalculatorButton * self) { calc_numeric(s...
  function btn_func_div (line 89) | static void btn_func_div(struct CalculatorButton * self) { calc_func("/"...
  function btn_func_mul (line 90) | static void btn_func_mul(struct CalculatorButton * self) { calc_func("*"...
  function btn_func_sub (line 91) | static void btn_func_sub(struct CalculatorButton * self) { calc_func("-"...
  function btn_func_add (line 92) | static void btn_func_add(struct CalculatorButton * self) { calc_func("+"...
  function btn_func_pct (line 93) | static void btn_func_pct(struct CalculatorButton * self) { calc_func("%"...
  function btn_func_opr (line 94) | static void btn_func_opr(struct CalculatorButton * self) { calc_func("("...
  function btn_func_cpr (line 95) | static void btn_func_cpr(struct CalculatorButton * self) { calc_func(")"...
  function btn_func_clr (line 96) | static void btn_func_clr(struct CalculatorButton * self) {
  function btn_func_equ (line 103) | static void btn_func_equ(struct CalculatorButton * self) {
  type CalculatorButton (line 137) | struct CalculatorButton
  function redraw (line 144) | static void redraw(void) {
  function redraw_window_callback (line 176) | static void redraw_window_callback(struct menu_bar * self) {
  function in_button (line 181) | int in_button(struct TTKButton * button, struct yutani_msg_window_mouse_...
  function setup_buttons (line 192) | void setup_buttons(void) {
  function resize_finish (line 223) | void resize_finish(int w, int h) {
  function clear_highlights (line 237) | static void clear_highlights(int *changed) {
  function set_hilight (line 246) | void set_hilight(struct TTKButton * button, int hilight) {
  function update_buttons (line 258) | static void update_buttons(struct yutani_msg_window_mouse_event * me, in...
  function _menu_action_exit (line 269) | static void _menu_action_exit(struct MenuEntry * entry) {
  function _menu_action_help (line 273) | static void _menu_action_help(struct MenuEntry * entry) {
  function _menu_action_about (line 278) | static void _menu_action_about(struct MenuEntry * entry) {
  function main (line 289) | int main(int argc, char * argv[]) {

FILE: apps/cat-img.c
  function get_cell_sizes (line 19) | void get_cell_sizes(int * w, int * h) {
  function raw_output (line 32) | void raw_output(void) {
  function unraw_output (line 39) | void unraw_output(void) {
  function usage (line 46) | int usage(char * argv[]) {
  function main (line 58) | int main (int argc, char * argv[]) {

FILE: apps/cat.c
  function doit (line 26) | void doit(int fd) {
  function main (line 40) | int main(int argc, char ** argv) {

FILE: apps/chmod.c
  type mode_set (line 21) | enum mode_set {
  function calc (line 27) | static int calc(int mode, int users) {
  function main (line 41) | int main(int argc, char * argv[]) {

FILE: apps/chown.c
  function usage (line 16) | static int usage(char * argv[]) {
  function invalid (line 21) | static int invalid(char * argv[], char c) {
  function parse_user_group (line 26) | static int parse_user_group(char * argv[], char * arg, uid_t * user, gid...
  function main (line 82) | int main(int argc, char * argv[]) {

FILE: apps/clear.c
  function main (line 16) | int main(int argc, char ** argv) {

FILE: apps/cmp.c
  function usage (line 20) | static int usage(char * argv[]) {
  function main (line 25) | int main(int argc, char * argv[]) {

FILE: apps/color-picker.c
  type TT_Font (line 41) | struct TT_Font
  function redraw_borders (line 43) | void redraw_borders() {
  function fmin (line 47) | double fmin(double a, double b) {
  function fmax (line 51) | double fmax(double a, double b) {
  function hsv_to_rgb (line 55) | uint32_t hsv_to_rgb(float h, float s, float v) {
  function rgb_to_hsv (line 70) | void rgb_to_hsv(uint32_t c, double *h, double *s, double *v) {
  type Picker (line 99) | struct Picker {
  function pt_sign (line 110) | static double pt_sign(const struct gfx_point *p1, const struct gfx_point...
  function in_triangle (line 114) | static int in_triangle(const struct gfx_point * pt, const struct gfx_poi...
  function gfx_fill_magic (line 129) | static uint32_t gfx_fill_magic(int32_t x, int32_t y, double alpha, void ...
  function fill_picker (line 177) | static void fill_picker(struct Picker *picker) {
  function draw_ring (line 196) | static void draw_ring(gfx_context_t * ctx, double x, double y, double ra...
  function redraw_everything (line 216) | static void redraw_everything(void) {
  function clamp_to_line (line 246) | static double clamp_to_line(struct gfx_point *p, const struct gfx_point ...
  function handle_mouse (line 260) | static void handle_mouse(struct yutani_msg_window_mouse_event * me) {
  function resize_finish (line 335) | void resize_finish(int w, int h) {
  function parseColor (line 352) | static uint32_t parseColor(const char * c) {
  function main (line 362) | int main (int argc, char ** argv) {

FILE: apps/compositor.c
  function usage (line 79) | static int usage(char * argv[]) {
  function parse_args (line 98) | static int parse_args(int argc, char * argv[], int * out) {
  function min (line 139) | static int32_t min(int32_t a, int32_t b) {
  function max (line 143) | static int32_t max(int32_t a, int32_t b) {
  function next_buf_id (line 147) | static int next_buf_id(void) {
  function next_wid (line 152) | static int next_wid(void) {
  function yutani_current_time (line 157) | uint64_t yutani_current_time(yutani_globals_t * yg) {
  function yutani_time_since (line 172) | uint64_t yutani_time_since(yutani_globals_t * yg, uint64_t start_time) {
  function yutani_device_to_window (line 183) | void yutani_device_to_window(yutani_server_window_t * window, int32_t x,...
  function yutani_window_to_device (line 210) | void yutani_window_to_device(yutani_server_window_t * window, int32_t x,...
  function list_t (line 231) | static list_t * window_zorder_owner(yutani_globals_t * yg, unsigned shor...
  function unorder_window (line 248) | static void unorder_window(yutani_globals_t * yg, yutani_server_window_t...
  function reorder_window (line 271) | static void reorder_window(yutani_globals_t * yg, yutani_server_window_t...
  function make_top (line 306) | static void make_top(yutani_globals_t * yg, yutani_server_window_t * w) {
  function set_focused_window (line 325) | static void set_focused_window(yutani_globals_t * yg, yutani_server_wind...
  function yutani_server_window_t (line 362) | static yutani_server_window_t * get_focused(yutani_globals_t * yg) {
  function yutani_pick_animation (line 368) | static int yutani_pick_animation(uint32_t flags, int direction) {
  function yutani_server_window_t (line 386) | static yutani_server_window_t * server_window_create(yutani_globals_t * ...
  function server_window_update_shape (line 447) | static void server_window_update_shape(yutani_globals_t * yg, yutani_ser...
  function server_window_resize (line 460) | static uint32_t server_window_resize(yutani_globals_t * yg, yutani_serve...
  function server_window_resize_finish (line 485) | static void server_window_resize_finish(yutani_globals_t * yg, yutani_se...
  function mark_screen (line 543) | static void mark_screen(yutani_globals_t * yg, int32_t x, int32_t y, int...
  function draw_cursor (line 557) | static void draw_cursor(yutani_globals_t * yg, int x, int y, int cursor) {
  function yutani_server_window_t (line 626) | static yutani_server_window_t * check_top_at(yutani_globals_t * yg, yuta...
  function yutani_server_window_t (line 647) | static yutani_server_window_t * top_at(yutani_globals_t * yg, uint16_t x...
  function set_focused_at (line 672) | static void set_focused_at(yutani_globals_t * yg, int x, int y) {
  function yutani_window_is_top (line 683) | int yutani_window_is_top(yutani_globals_t * yg, yutani_server_window_t *...
  function yutani_window_is_bottom (line 688) | int yutani_window_is_bottom(yutani_globals_t * yg, yutani_server_window_...
  function yutani_color_for_wid (line 698) | uint32_t yutani_color_for_wid(yutani_wid_t wid) {
  function matrix_is_translation (line 722) | static inline int matrix_is_translation(gfx_matrix_t m) {
  function apply_rotation (line 726) | static void apply_rotation(yutani_globals_t * yg, yutani_server_window_t...
  function yutani_blit_window (line 756) | static int yutani_blit_window(yutani_globals_t * yg, yutani_server_windo...
  function yutani_post_vbox_rects (line 901) | static void yutani_post_vbox_rects(yutani_globals_t * yg) {
  function yutani_blit_windows (line 969) | static void yutani_blit_windows(yutani_globals_t * yg) {
  function yutani_screenshot (line 992) | static void yutani_screenshot(yutani_globals_t * yg) {
  function gfx_context_t (line 1079) | static gfx_context_t * init_graphics_with_store(gfx_context_t * base, ch...
  function resize_display (line 1092) | static void resize_display(yutani_globals_t * yg) {
  function redraw_windows (line 1138) | static void redraw_windows(yutani_globals_t * yg) {
  function yutani_clip_init (line 1341) | void yutani_clip_init(yutani_globals_t * yg) {
  function mark_window_relative (line 1351) | static void mark_window_relative(yutani_globals_t * yg, yutani_server_wi...
  function mark_window (line 1417) | static void mark_window(yutani_globals_t * yg, yutani_server_window_t * ...
  function window_mark_for_close (line 1424) | static void window_mark_for_close(yutani_globals_t * yg, yutani_server_w...
  function window_remove_from_client (line 1436) | static void window_remove_from_client(yutani_globals_t * yg, yutani_serv...
  function window_finish_minimize (line 1447) | static void window_finish_minimize(yutani_globals_t * yg, yutani_server_...
  function window_actually_close (line 1473) | static void window_actually_close(yutani_globals_t * yg, yutani_server_w...
  function ad_flags (line 1528) | static uint32_t ad_flags(yutani_globals_t * yg, yutani_server_window_t *...
  function yutani_query_result (line 1542) | static void yutani_query_result(yutani_globals_t * yg, uintptr_t dest, y...
  function notify_subscribers (line 1553) | static void notify_subscribers(yutani_globals_t * yg) {
  function window_move (line 1578) | static void window_move(yutani_globals_t * yg, yutani_server_window_t * ...
  function window_tile (line 1595) | static void window_tile(yutani_globals_t * yg, yutani_server_window_t * ...
  function window_untile (line 1659) | static void window_untile(yutani_globals_t * yg, yutani_server_window_t ...
  function window_reveal (line 1667) | static void window_reveal(yutani_globals_t * yg, yutani_server_window_t ...
  function window_unminimize (line 1675) | static void window_unminimize(yutani_globals_t * yg, yutani_server_windo...
  function window_minimize (line 1692) | static void window_minimize(yutani_globals_t * yg, yutani_server_window_...
  function handle_key_event (line 1704) | static void handle_key_event(yutani_globals_t * yg, struct yutani_msg_ke...
  function add_key_bind (line 1905) | static void add_key_bind(yutani_globals_t * yg, struct yutani_msg_key_bi...
  function adjust_window_opacity (line 1922) | static void adjust_window_opacity(yutani_globals_t * yg, int direction) {
  function mouse_stop_drag (line 1938) | static void mouse_stop_drag(yutani_globals_t * yg) {
  function mouse_start_drag (line 1944) | static void mouse_start_drag(yutani_globals_t * yg, yutani_server_window...
  function mouse_start_rotate (line 1970) | static void mouse_start_rotate(yutani_globals_t * yg) {
  function mouse_start_resize (line 1991) | static void mouse_start_resize(yutani_globals_t * yg, yutani_scale_direc...
  function handle_mouse_event (line 2056) | static void handle_mouse_event(yutani_globals_t * yg, struct yutani_msg_...
  function yutani_display_resize_handle (line 2334) | static void yutani_display_resize_handle(int signum) {
  type font_def (line 2344) | struct font_def {
  type font_def (line 2352) | struct font_def
  function load_fonts (line 2382) | static void load_fonts(yutani_globals_t * yg) {
  function main (line 2398) | int main(int argc, char * argv[]) {

FILE: apps/cp.c
  function copy_link (line 29) | static int copy_link(char * source, char * dest, int mode, int uid, int ...
  function copy_file (line 40) | static int copy_file(char * source, char * dest, int mode,int uid, int g...
  function copy_directory (line 94) | static int copy_directory(char * source, char * dest, int mode, int uid,...
  function copy_thing (line 133) | static int copy_thing(char * tmp, char * tmp2) {
  function copy_top_level (line 157) | static int copy_top_level(char **argv, int argc, int optind) {
  function main (line 185) | int main(int argc, char ** argv) {

FILE: apps/cpuwidget.c
  type menu_bar (line 36) | struct menu_bar
  type menu_bar_entries (line 37) | struct menu_bar_entries
  type TT_Font (line 57) | struct TT_Font
  type TT_Font (line 58) | struct TT_Font
  function hsv_to_rgb (line 60) | uint32_t hsv_to_rgb(float h, float s, float v) {
  function get_cpu_info (line 80) | static void get_cpu_info(int cpus[]) {
  function plot_graph (line 109) | static void plot_graph(gfx_context_t * ctx, size_t scale, long samples[1...
  function draw_lines (line 165) | static void draw_lines(gfx_context_t * ctx) {
  function draw_cpu_graphs (line 177) | static void draw_cpu_graphs(gfx_context_t * ctx, float shift) {
  function next_cpu (line 185) | static void next_cpu(gfx_context_t * ctx) {
  function get_mem_info (line 197) | static void get_mem_info(int * total, int * used) {
  function draw_mem_graphs (line 223) | static void draw_mem_graphs(gfx_context_t * ctx, float shift) {
  function next_mem (line 229) | static void next_mem(gfx_context_t * ctx) {
  function count_interfaces (line 250) | static int count_interfaces(void) {
  function refresh_interfaces (line 268) | static void refresh_interfaces(size_t ifs[32]) {
  function draw_net_graphs (line 304) | static void draw_net_graphs(gfx_context_t * ctx, float shift) {
  function next_net (line 312) | static void next_net(gfx_context_t * ctx) {
  function draw_legend_element (line 361) | static void draw_legend_element(int which, int count, int index, uint32_...
  function draw_legend_cpu (line 389) | static void draw_legend_cpu(void) {
  function draw_legend_mem (line 397) | static void draw_legend_mem(void) {
  function draw_legend_net (line 401) | static void draw_legend_net(void) {
  function redraw_graphs (line 410) | static void redraw_graphs(void) {
  function refresh (line 417) | static void refresh(clock_t ticks) {
  function redraw_net_scale (line 435) | static void redraw_net_scale(void) {
  function render_base (line 447) | void render_base(void) {
  function redraw_window_callback (line 452) | static void redraw_window_callback(struct menu_bar * self) {
  function initial_stuff (line 459) | static void initial_stuff(void) {
  function resize_finish (line 504) | void resize_finish(int w, int h) {
  function _menu_action_exit (line 530) | static void _menu_action_exit(struct MenuEntry * entry) {
  function _menu_action_help (line 534) | static void _menu_action_help(struct MenuEntry * entry) {
  function _menu_action_about (line 539) | static void _menu_action_about(struct MenuEntry * entry) {
  function main (line 551) | int main (int argc, char ** argv) {

FILE: apps/crc32.c
  function main (line 61) | int main(int argc, char * argv[]) {

FILE: apps/cursor-off.c
  function main (line 19) | int main(int argc, char * argv[]) {

FILE: apps/date.c
  function show_usage (line 23) | static void show_usage(int argc, char * argv[]) {
  function digits (line 36) | int digits(const char * s, int len) {
  function mmddhhmm (line 43) | int mmddhhmm(struct tm * tm, const char * str) {
  function ddyy (line 62) | int ddyy(struct tm * tm, const char * str) {
  function secs (line 68) | int secs(struct tm * tm, const char * str) {
  function main (line 75) | int main(int argc, char * argv[]) {

FILE: apps/dbg.c
  function dump_regs (line 38) | static void dump_regs(struct URegs * r) {
  function data_read_bytes (line 83) | static int data_read_bytes(pid_t pid, uintptr_t addr, char * buf, size_t...
  function data_read_int (line 92) | static int data_read_int(pid_t pid, uintptr_t addr) {
  function data_read_ptr (line 98) | static uintptr_t data_read_ptr(pid_t pid, uintptr_t addr) {
  function string_arg (line 104) | static void string_arg(pid_t pid, uintptr_t ptr, size_t maxsize) {
  type elf_t (line 154) | typedef struct elf_object {
  function find_symbol (line 171) | static int find_symbol(pid_t pid, uintptr_t addr_in, char ** name, uintp...
  function show_libs (line 330) | static void show_libs(pid_t pid) {
  function attempt_backtrace (line 351) | static void attempt_backtrace(pid_t pid, struct URegs * regs) {
  function imatch (line 377) | static int imatch(const char * a, const char * b) {
  function signal_from_string (line 386) | static int signal_from_string(const char * str) {
  function show_commandline (line 404) | static void show_commandline(pid_t pid, int status, struct URegs * regs) {
  function usage (line 583) | static int usage(char * argv[]) {
  type stat (line 603) | struct stat
  function pass_sig (line 638) | static void pass_sig(int sig) {
  function main (line 643) | int main(int argc, char * argv[]) {

FILE: apps/demo.c
  type TT_Font (line 20) | struct TT_Font
  type tm (line 21) | struct tm
  function redraw (line 24) | static void redraw(void) {
  function main (line 42) | int main(int argc, char * argv[]) {

FILE: apps/dhclient.c
  type ethernet_packet (line 23) | struct ethernet_packet {
  type ipv4_packet (line 30) | struct ipv4_packet {
  type udp_packet (line 44) | struct udp_packet {
  type dhcp_packet (line 52) | struct dhcp_packet {
  type dns_packet (line 78) | struct dns_packet {
  type tcp_header (line 88) | struct tcp_header {
  type tcp_check_header (line 103) | struct tcp_check_header {
  type payload (line 145) | struct payload {
  function ip_ntoa (line 153) | static void ip_ntoa(const uint32_t src_addr, char * out) {
  function calculate_ipv4_checksum (line 161) | uint16_t calculate_ipv4_checksum(struct ipv4_packet * p) {
  function fill (line 180) | void fill(struct payload *it, size_t payload_size) {
  function time_diff (line 239) | static void time_diff(struct timeval *start, struct timeval *end, time_t...
  function configure_interface (line 250) | static int configure_interface(const char * if_name) {
  function configure_interface_with_backoff (line 422) | static int configure_interface_with_backoff(const char * if_name) {
  function main (line 433) | int main(int argc, char * argv[]) {

FILE: apps/dirname.c
  function main (line 13) | int main(int argc, char * argv[]) {

FILE: apps/drawlines.c
  function draw (line 34) | static void draw(void) {
  function show_usage (line 43) | static void show_usage(char * argv[]) {
  function main (line 55) | int main (int argc, char ** argv) {

FILE: apps/du.c
  function print_human_readable_size (line 29) | static int print_human_readable_size(char * _out, size_t s) {
  function print_size (line 44) | static void print_size(uint64_t size, char * name) {
  function count_directory (line 57) | static uint64_t count_directory(char * source) {
  function count_thing (line 89) | static uint64_t count_thing(char * tmp) {
  function main (line 103) | int main(int argc, char * argv[]) {

FILE: apps/echo.c
  function show_usage (line 17) | void show_usage(char * argv[]) {
  function main (line 29) | int main(int argc, char ** argv) {

FILE: apps/env.c
  function main (line 17) | int main(int argc, char ** argv) {

FILE: apps/esh.c
  type semaphore (line 81) | struct semaphore {
  function create_semaphore (line 85) | struct semaphore create_semaphore(void) {
  function raise_semaphore (line 91) | void raise_semaphore(struct semaphore s){
  function wait_semaphore (line 97) | void wait_semaphore(struct semaphore s) {
  function set_pgid (line 104) | void set_pgid(int pgid) {
  function set_pgrp (line 110) | void set_pgrp(int pgid) {
  function reset_pgrp (line 121) | void reset_pgrp() {
  function shell_install_command (line 125) | void shell_install_command(char * name, shell_command_t func, char * des...
  function shell_command_t (line 139) | shell_command_t shell_find(char * str) {
  function getuser (line 163) | void getuser() {
  function gethost (line 173) | void gethost() {
  function display_width_of_string (line 182) | int display_width_of_string(const char * str) {
  function print_extended_ps (line 199) | void print_extended_ps(char * format, char * buffer, int * display_width) {
  function sig_break_loop (line 370) | void sig_break_loop(int sig) {
  function tab_complete_func (line 381) | void tab_complete_func(rline_context_t * c) {
  function add_argument (line 712) | void add_argument(list_t * argv, char * buf) {
  function add_environment (line 719) | void add_environment(list_t * env) {
  function read_entry (line 729) | int read_entry(char * buffer) {
  function read_entry_continued (line 747) | int read_entry_continued(char * buffer) {
  function variable_char (line 756) | int variable_char(uint8_t c) {
  function variable_char_first (line 764) | int variable_char_first(uint8_t c) {
  type alternative (line 771) | struct alternative {
  type alternative (line 781) | struct alternative
  function run_cmd (line 803) | void run_cmd(char ** args) {
  function is_number (line 837) | int is_number(const char * c) {
  function handle_status (line 848) | static void handle_status(int ret_code) {
  function wait_for_child (line 866) | int wait_for_child(int pgid, char * name, int retpid) {
  function shell_exec (line 908) | int shell_exec(char * buffer, size_t size, FILE * file, char ** out_buff...
  function add_path_contents (line 1567) | void add_path_contents(char * path) {
  type command (line 1586) | struct command {
  function comp_shell_commands (line 1592) | static int comp_shell_commands(const void *p1, const void *p2) {
  function sort_commands (line 1596) | void sort_commands() {
  function show_version (line 1611) | void show_version(void) {
  function show_usage (line 1615) | void show_usage(int argc, char * argv[]) {
  function add_path (line 1629) | void add_path(void) {
  function run_script (line 1653) | int run_script(FILE * f) {
  function source_eshrc (line 1674) | void source_eshrc(void) {
  function main (line 1689) | int main(int argc, char ** argv) {
  function shell_cmd_cd (line 1812) | uint32_t shell_cmd_cd(int argc, char * argv[]) {
  function shell_cmd_history (line 1840) | uint32_t shell_cmd_history(int argc, char * argv[]) {
  function shell_cmd_export (line 1847) | uint32_t shell_cmd_export(int argc, char * argv[]) {
  function shell_cmd_exit (line 1857) | uint32_t shell_cmd_exit(int argc, char * argv[]) {
  function shell_cmd_help (line 1866) | uint32_t shell_cmd_help(int argc, char * argv[]) {
  function shell_cmd_if (line 1889) | uint32_t shell_cmd_if(int argc, char * argv[]) {
  function shell_cmd_while (line 1980) | uint32_t shell_cmd_while(int argc, char * argv[]) {
  function shell_cmd_export_cmd (line 2038) | uint32_t shell_cmd_export_cmd(int argc, char * argv[]) {
  function shell_cmd_empty (line 2087) | uint32_t shell_cmd_empty(int argc, char * argv[]) {
  function shell_cmd_equals (line 2096) | uint32_t shell_cmd_equals(int argc, char * argv[]) {
  function shell_cmd_return (line 2103) | uint32_t shell_cmd_return(int argc, char * argv[]) {
  function shell_cmd_source (line 2109) | uint32_t shell_cmd_source(int argc, char * argv[]) {
  function shell_cmd_exec (line 2123) | uint32_t shell_cmd_exec(int argc, char * argv[]) {
  function shell_cmd_not (line 2128) | uint32_t shell_cmd_not(int argc, char * argv[]) {
  function shell_cmd_unset (line 2149) | uint32_t shell_cmd_unset(int argc, char * argv[]) {
  function shell_cmd_read (line 2163) | uint32_t shell_cmd_read(int argc, char * argv[]) {
  function get_available_job (line 2209) | int get_available_job(int argc, char * argv[]) {
  function shell_cmd_fg (line 2229) | uint32_t shell_cmd_fg(int argc, char * argv[]) {
  function describe_job (line 2251) | static void describe_job(pid_t pid) {
  function shell_cmd_bg (line 2255) | uint32_t shell_cmd_bg(int argc, char * argv[]) {
  function shell_cmd_jobs (line 2275) | uint32_t shell_cmd_jobs(int argc, char * argv[]) {
  function shell_cmd_rehash (line 2286) | uint32_t shell_cmd_rehash(int argc, char * argv[]) {
  function shell_cmd_time (line 2309) | uint32_t shell_cmd_time(int argc, char * argv[]) {
  function install_commands (line 2365) | void install_commands() {

FILE: apps/false.c
  function main (line 9) | int main() {

FILE: apps/fetch.c
  type http_req (line 28) | struct http_req {
  type timeval (line 46) | struct timeval
  function parse_url (line 52) | int parse_url(char * d, struct http_req * r) {
  function print_progress (line 89) | void print_progress(int force) {
  function usage (line 125) | int usage(char * argv[]) {
  function collect_password (line 145) | int collect_password(char * password) {
  function read_http_line (line 165) | void read_http_line(char * buf, FILE * f) {
  function bad_response (line 181) | void bad_response(void) {
  function http_fetch (line 186) | int http_fetch(FILE * f) {
  function main (line 269) | int main(int argc, char * argv[]) {

FILE: apps/file-browser.c
  type File (line 42) | struct File {
  type File (line 77) | struct File
  type TT_Font (line 81) | struct TT_Font
  type TT_Font (line 82) | struct TT_Font
  type MenuEntry (line 84) | struct MenuEntry
  type MenuEntry (line 85) | struct MenuEntry
  type MenuEntry (line 86) | struct MenuEntry
  type MenuEntry (line 87) | struct MenuEntry
  type MenuEntry (line 88) | struct MenuEntry
  type MenuEntry (line 89) | struct MenuEntry
  type timeval (line 99) | struct timeval
  type menu_bar (line 110) | struct menu_bar
  type menu_bar_entries (line 111) | struct menu_bar_entries
  type MenuList (line 121) | struct MenuList
  type MenuList (line 122) | struct MenuList
  function precise_current_time (line 130) | static uint64_t precise_current_time(void) {
  function precise_time_since (line 140) | static uint64_t precise_time_since(uint64_t start_time) {
  function _decor_get_bounds (line 153) | static int _decor_get_bounds(yutani_window_t * win, struct decor_bounds ...
  function _close_enough (line 170) | static int _close_enough(struct yutani_msg_window_mouse_event * me) {
  function clear_offset (line 189) | static void clear_offset(int offset) {
  function print_human_readable_size (line 196) | static int print_human_readable_size(char * _out, uint64_t s) {
  function draw_file (line 219) | static void draw_file(struct File * f, int offset) {
  type File (line 355) | struct File
  function redraw_files (line 365) | static void redraw_files(void) {
  function set_title (line 377) | static void set_title(char * directory) {
  function has_extension (line 400) | static int has_extension(struct File * f, char * extension) {
  function update_status (line 426) | static void update_status(void) {
  function load_directory (line 457) | static void load_directory(const char * path, int modifies_history) {
  function reinitialize_contents (line 800) | static void reinitialize_contents(void) {
  function _draw_buttons (line 856) | static void _draw_buttons(struct decor_bounds bounds) {
  function _figure_out_navbar_cursor (line 885) | static void _figure_out_navbar_cursor(int x, struct decor_bounds bounds) {
  function _recalculate_nav_bar_cursor (line 909) | static void _recalculate_nav_bar_cursor(void) {
  function _draw_nav_bar (line 926) | static void _draw_nav_bar(struct decor_bounds bounds) {
  function _draw_status (line 971) | static void _draw_status(struct decor_bounds bounds) {
  function _redraw_nav_bar (line 1006) | static void _redraw_nav_bar(void) {
  function maybe_blink_cursor (line 1017) | static void maybe_blink_cursor(void) {
  function nav_bar_set_focused (line 1038) | static void nav_bar_set_focused(void) {
  function nav_bar_backspace_word (line 1047) | static void nav_bar_backspace_word(void) {
  function nav_bar_backspace (line 1073) | static void nav_bar_backspace(void) {
  function nav_bar_delete (line 1089) | static void nav_bar_delete(void) {
  function nav_bar_insert_char (line 1106) | static void nav_bar_insert_char(char c) {
  function nav_bar_cursor_left (line 1123) | static void nav_bar_cursor_left(int modifiers) {
  function nav_bar_cursor_right (line 1145) | static void nav_bar_cursor_right(int modifiers) {
  function redraw_window (line 1167) | static void redraw_window(void) {
  function draw_background (line 1224) | static void draw_background(int width, int height) {
  function resize_finish (line 1304) | static void resize_finish(int w, int h) {
  function _menu_action_input_path (line 1351) | static void _menu_action_input_path(struct MenuEntry * entry) {
  function _menu_action_exit (line 1357) | static void _menu_action_exit(struct MenuEntry * entry) {
  function _menu_action_navigate (line 1362) | static void _menu_action_navigate(struct MenuEntry * entry) {
  function _menu_action_up (line 1371) | static void _menu_action_up(struct MenuEntry * entry) {
  function _menu_action_refresh (line 1381) | static void _menu_action_refresh(struct MenuEntry * entry) {
  function _menu_action_help (line 1389) | static void _menu_action_help(struct MenuEntry * entry) {
  function _menu_action_copy (line 1396) | static void _menu_action_copy(struct MenuEntry * entry) {
  function _menu_action_paste (line 1432) | static void _menu_action_paste(struct MenuEntry * entry) {
  function _menu_action_delete (line 1436) | static void _menu_action_delete(struct MenuEntry * entry) {
  function _menu_action_about (line 1475) | static void _menu_action_about(struct MenuEntry * entry) {
  function launch_application (line 1490) | static void launch_application(char * app) {
  function launch_application_menu (line 1502) | static void launch_application_menu(struct MenuEntry * self) {
  function open_file (line 1510) | static void open_file(struct File * f) {
  function _menu_action_open (line 1551) | static void _menu_action_open(struct MenuEntry * self) {
  function _menu_action_edit (line 1560) | static void _menu_action_edit(struct MenuEntry * self) {
  function _menu_action_toggle_hidden (line 1571) | static void _menu_action_toggle_hidden(struct MenuEntry * self) {
  function _menu_action_select_all (line 1577) | static void _menu_action_select_all(struct MenuEntry * self) {
  function set_view_mode (line 1594) | static void set_view_mode(int mode) {
  function _menu_action_view_mode (line 1620) | static void _menu_action_view_mode(struct MenuEntry * entry) {
  function handle_clipboard (line 1649) | static void handle_clipboard(char * contents) {
  function toggle_selected (line 1693) | static void toggle_selected(int hilighted_offset, int modifiers) {
  function _set_hilight (line 1727) | static void _set_hilight(int index, int hilight) {
  function _handle_button_press (line 1748) | static void _handle_button_press(int index) {
  function _scroll_up (line 1795) | static void _scroll_up(void) {
  function _scroll_down (line 1805) | static void _scroll_down(void) {
  function sig_usr2 (line 1822) | static void sig_usr2(int sig) {
  function sig_usr1 (line 1830) | static void sig_usr1(int sig) {
  function sig_urg (line 1834) | static void sig_urg(int sig) {
  function arrow_select (line 1844) | static void arrow_select(int x, int y) {
  function redraw_window_callback (line 1897) | static void redraw_window_callback(struct menu_bar * self) {
  function show_context_menu (line 1902) | static void show_context_menu(struct yutani_msg_window_mouse_event * me) {
  function set_signal_handler (line 1925) | static void set_signal_handler(int signum, void (*handler)(int)) {
  function main (line 1933) | int main(int argc, char * argv[]) {

FILE: apps/find-timezone.c
  type Value (line 21) | typedef struct JSON_Value Value;
  function main (line 25) | int main(int argc, char * argv[]) {

FILE: apps/font-preview.c
  type TT_Font (line 24) | struct TT_Font
  type TT_Font (line 36) | struct TT_Font
  function redraw (line 41) | void redraw(void) {
  function resize_finish (line 74) | void resize_finish(int w, int h) {
  function main (line 97) | int main(int argc, char * argv[]) {

FILE: apps/font-tool.c
  function usage (line 16) | static void usage(char * argv[]) {
  type TT_Font (line 31) | struct TT_Font
  function main (line 33) | int main(int argc, char * argv[]) {

FILE: apps/free.c
  function show_usage (line 14) | void show_usage(int argc, char * argv[]) {
  function main (line 28) | int main(int argc, char * argv[]) {

FILE: apps/getty.c
  function main (line 24) | int main(int argc, char * argv[]) {

FILE: apps/glogin-provider.c
  type TT_Font (line 60) | struct TT_Font
  type TT_Font (line 61) | struct TT_Font
  function center_x (line 66) | int center_x(int x) {
  function center_y (line 70) | int center_y(int y) {
  function buffer_put (line 75) | int buffer_put(char * input_buffer, char c) {
  type text_box (line 97) | struct text_box {
  type login_container (line 116) | struct login_container {
  function draw_text_box (line 128) | void draw_text_box(gfx_context_t * ctx, struct text_box * tb) {
  function draw_login_container (line 168) | void draw_login_container(gfx_context_t * ctx, struct login_container * ...
  function get_updated_hostname_with_time_info (line 191) | static void get_updated_hostname_with_time_info(char hostname[]) {
  function main (line 208) | int main (int argc, char ** argv) {

FILE: apps/glogin.c
  function main (line 25) | int main (int argc, char ** argv) {

FILE: apps/grep.c
  type MatchQualifier (line 42) | struct MatchQualifier {
  type match_op (line 53) | typedef enum {
  function match_char_internal (line 62) | static inline int match_char_internal(char a, char b, int ignorecase, ma...
  function match_char (line 79) | int match_char(struct MatchQualifier * self, char b, int mode) {
  function match_squares (line 86) | int match_squares(struct MatchQualifier * self, char c, int mode) {
  function match_dot (line 120) | int match_dot(struct MatchQualifier * self, char c, int mode) {
  type Line (line 124) | struct Line {
  function regex_matches (line 129) | int regex_matches(struct Line * line, int j, char * needle, int ignoreca...
  function subsearch_matches (line 234) | static int subsearch_matches(struct Line * line, int j, char * needle, i...
  function usage (line 245) | int usage(char ** argv) {
  function main (line 318) | int main(int argc, char ** argv) {

FILE: apps/groups.c
  function main (line 15) | int main(int argc, char ** argv) {

FILE: apps/gsudo.c
  type TT_Font (line 41) | struct TT_Font
  type TTKButton (line 43) | struct TTKButton
  type TTKButton (line 47) | struct TTKButton
  type TTKButton (line 51) | struct TTKButton
  function in_button (line 53) | static int in_button(struct TTKButton * button, struct yutani_msg_window...
  function set_hilight (line 62) | static int set_hilight(struct TTKButton * button, int hilight) {
  function redraw (line 76) | static void redraw(char * username, char * password, int fails, char * a...
  function graphical_callback (line 136) | static int graphical_callback(char * username, char * password, int fail...
  function main (line 226) | int main(int argc, char ** argv) {

FILE: apps/gunzip.c
  function _get (line 22) | static uint8_t _get(struct inflate_context * ctx) {
  function _write (line 26) | static void _write(struct inflate_context * ctx, unsigned int sym) {
  function usage (line 30) | static int usage(int argc, char * argv[]) {
  function endswith (line 44) | static int endswith(char * str, char * suffix) {
  function decompress_one (line 52) | static int decompress_one(char * argv[], char * file) {
  function main (line 118) | int main(int argc, char * argv[]) {

FILE: apps/head.c
  function main (line 16) | int main(int argc, char * argv[]) {

FILE: apps/hello.c
  function main (line 11) | int main(int argc, char * argv[]) {

FILE: apps/help-browser.c
  type TT_Font (line 53) | struct TT_Font
  type TT_Font (line 54) | struct TT_Font
  type TT_Font (line 55) | struct TT_Font
  type TT_Font (line 56) | struct TT_Font
  type TT_Font (line 57) | struct TT_Font
  type Char (line 59) | struct Char {
  type TT_Font (line 67) | struct TT_Font
  function current_size (line 82) | static int current_size(void) {
  function buffer_width (line 89) | static int buffer_width(list_t * buffer) {
  function draw_buffer (line 102) | static int draw_buffer(list_t * buffer) {
  function current_line_height (line 121) | static int current_line_height(void) {
  function write_buffer (line 129) | static void write_buffer(void) {
  function parser_open (line 137) | static int parser_open(struct markup_state * self, void * user, struct m...
  function parser_close (line 159) | static int parser_close(struct markup_state * self, void * user, char * ...
  function parser_data (line 183) | static int parser_data(struct markup_state * self, void * user, char * d...
  type menu_bar (line 221) | struct menu_bar
  type menu_bar_entries (line 222) | struct menu_bar_entries
  function _menu_action_exit (line 229) | static void _menu_action_exit(struct MenuEntry * entry) {
  function reinitialize_contents (line 233) | static void reinitialize_contents(void) {
  function redraw_window (line 297) | static void redraw_window(void) {
  function resize_finish (line 321) | static void resize_finish(int w, int h) {
  type dirent (line 346) | struct dirent
  function navigate (line 378) | static void navigate(const char * t) {
  function _scroll_up (line 427) | static void _scroll_up(void) {
  function _scroll_down (line 434) | static void _scroll_down(void) {
  function _menu_action_navigate (line 450) | static void _menu_action_navigate(struct MenuEntry * entry) {
  function _menu_action_back (line 457) | static void _menu_action_back(struct MenuEntry * entry) {
  function _menu_action_forward (line 461) | static void _menu_action_forward(struct MenuEntry * entry) {
  function _menu_action_about (line 466) | static void _menu_action_about(struct MenuEntry * entry) {
  function redraw_window_callback (line 477) | static void redraw_window_callback(struct menu_bar * self) {
  function main (line 482) | int main(int argc, char * argv[]) {

FILE: apps/hexify.c
  function print_line (line 18) | void print_line(unsigned char * buf, size_t width, size_t sizer, size_t ...
  function stoih (line 50) | static int stoih(size_t w, char c[w], size_t *out) {
  function usage (line 69) | static int usage(char * argv[]) {
  function main (line 83) | int main(int argc, char * argv[]) {

FILE: apps/hostname.c
  function main (line 13) | int main(int argc, char * argv[]) {

FILE: apps/ifconfig.c
  function ip_ntoa (line 30) | static void ip_ntoa(const uint32_t src_addr, char * out) {
  function print_human_readable_size (line 56) | static int print_human_readable_size(char * _out, size_t s) {
  function open_netdev (line 69) | static int open_netdev(const char * if_name) {
  function print_interface (line 75) | static int print_interface(const char * if_name) {
  function print_all_interfaces (line 143) | static int print_all_interfaces(void) {
  function maybe_address (line 167) | static int maybe_address(const char * s) {
  function parse_address (line 182) | static int parse_address(const char * cmd, const char * addr, in_addr_t ...
  function _set_address (line 196) | static int _set_address(int netdev, const char * cmd, const char * arg, ...
  function main (line 207) | int main(int argc, char * argv[]) {

FILE: apps/imgviewer.c
  function usage (line 54) | void usage(char * argv[]) {
  function decors (line 64) | static void decors() {
  function redraw (line 74) | void redraw() {
  function resize_finish (line 104) | void resize_finish(int w, int h) {
  function one_fifth (line 127) | static int one_fifth(int scale) {
  function main (line 133) | int main(int argc, char * argv[]) {

FILE: apps/init.c
  function set_console (line 47) | void set_console(void) {
  function start_options (line 54) | int start_options(char * args[]) {
  function main (line 92) | int main(int argc, char * argv[]) {

FILE: apps/insmod.c
  function main (line 14) | int main(int argc, char * argv[]) {

FILE: apps/irc.c
  type color_pair (line 43) | struct color_pair {
  function show_usage (line 48) | static void show_usage(int argc, char * argv[]) {
  type termios (line 62) | struct termios
  function set_unbuffered (line 64) | static void set_unbuffered() {
  function set_buffered (line 71) | static void set_buffered() {
  function user_color (line 75) | static int user_color(char * user) {
  function irc_color_to_pair (line 96) | static struct color_pair irc_color_to_pair(int fg, int bg) {
  function get_time (line 112) | static void get_time(int * h, int * m, int * s) {
  function print_color (line 122) | static void print_color(struct color_pair t) {
  function WRITE (line 147) | static void WRITE(const char * fmt, ...) {
  function handle (line 250) | static void handle(char * line) {
  function redraw_buffer (line 359) | static void redraw_buffer(char * buf) {
  function handle_input (line 377) | void handle_input(char * buf) {
  function main (line 414) | int main(int argc, char * argv[]) {

FILE: apps/json-test.c
  type Value (line 16) | typedef struct JSON_Value Value;
  function main (line 18) | int main(int argc, char * argv[]) {

FILE: apps/julia.c
  function hsv_to_rgb (line 65) | static uint32_t hsv_to_rgb(float h, float s, float v) {
  function hue_palette (line 80) | static uint32_t hue_palette(int k) {
  function rhue_palette (line 86) | static uint32_t rhue_palette(int k) {
  function bnw_palette (line 92) | static uint32_t bnw_palette(int k) {
  function mix (line 96) | static uint32_t mix(uint32_t base, uint32_t mixer, float ratio) {
  function wiki_palette (line 103) | static uint32_t wiki_palette(int k) {
  function initialize_palette (line 149) | static void initialize_palette(void) {
  function next_palette (line 159) | static void next_palette(void) {
  function julia (line 170) | static uint32_t julia(int xpt, int ypt) {
  function mandelbrot (line 189) | static uint32_t mandelbrot(int xpt, int ypt) {
  function usage (line 214) | void usage(char * argv[]) {
  function decors (line 235) | static void decors() {
  function do_line (line 239) | static void do_line(gfx_context_t * ctx, int j) {
  function start_processing (line 257) | void start_processing(void) {
  function draw_label (line 281) | void draw_label(void) {
  function step_once (line 321) | void step_once(void) {
  function resize_finish (line 365) | void resize_finish(int w, int h) {
  function amount (line 390) | static double amount(struct yutani_msg_key_event * ke, double basis) {
  function main (line 397) | int main(int argc, char * argv[]) {

FILE: apps/kbd-test.c
  function placech (line 19) | static void placech(unsigned char c, int x, int y, int attr) {
  function clear_screen (line 26) | static void clear_screen(void) {
  function redraw (line 37) | static void redraw(void) {
  function print_scancode (line 44) | static void print_scancode(unsigned int sc) {
  function main (line 57) | int main(int argc, char * argv[]) {

FILE: apps/kcmdline.c
  function show_usage (line 28) | void show_usage(int argc, char * argv[]) {
  function main (line 41) | int main(int argc, char * argv[]) {

FILE: apps/kill.c
  type sig_def (line 19) | struct sig_def {
  type sig_def (line 24) | struct sig_def
  function usage (line 64) | void usage(char * argv[]) {
  function main (line 76) | int main(int argc, char * argv[]) {

FILE: apps/killall.c
  type p_t (line 24) | typedef struct process {
  function p_t (line 34) | p_t * build_entry(struct dirent * dent) {
  function show_usage (line 91) | void show_usage(int argc, char * argv[]) {
  type sig_def (line 102) | struct sig_def {
  type sig_def (line 107) | struct sig_def
  function main (line 147) | int main (int argc, char * argv[]) {

FILE: apps/live-session.c
  function main (line 22) | int main(int argc, char * argv[]) {

FILE: apps/ln.c
  function main (line 24) | int main(int argc, char * argv[]) {

FILE: apps/login-loop.c
  type colorNames (line 28) | struct colorNames {
  type in_addr (line 79) | struct in_addr
  type dirent (line 86) | struct dirent
  function print_issue (line 99) | void print_issue(void) {
  function main (line 193) | int main(int argc, char * argv[]) {

FILE: apps/login.c
  function sig_pass (line 32) | void sig_pass(int sig) {
  function sig_segv (line 40) | void sig_segv(int sig) {
  function main (line 46) | int main(int argc, char ** argv) {

FILE: apps/logname.c
  function main (line 12) | int main(int argc, char ** argv) {

FILE: apps/ls.c
  type tfile (line 62) | struct tfile {
  type stat (line 69) | struct stat
  function filecmp (line 91) | static int filecmp(const void * c1, const void * c2) {
  function filecmp_notypesort (line 104) | static int filecmp_notypesort(const void * c1, const void * c2) {
  function print_entry (line 111) | static void print_entry(struct tfile * file, int colwidth) {
  function print_username (line 127) | static int print_username(char * _out, int uid) {
  function print_human_readable_size (line 146) | static int print_human_readable_size(char * _out, size_t s) {
  function update_column_widths (line 158) | static void update_column_widths(int * widths, struct tfile * file) {
  function print_entry_long (line 187) | static void print_entry_long(int * widths, struct tfile * file) {
  function show_usage (line 251) | static void show_usage(int argc, char * argv[]) {
  function display_tfiles (line 264) | static void display_tfiles(struct tfile ** ents_array, int numents) {
  function display_dir (line 302) | static int display_dir(char * p) {
  function main (line 364) | int main (int argc, char * argv[]) {

FILE: apps/lspci.c
  type device_class (line 16) | struct device_class {
  function show_usage (line 172) | static void show_usage(char * argv[]) {
  function main (line 183) | int main(int argc, char * argv[]) {

FILE: apps/migrate.c
  function copy_link (line 40) | void copy_link(char * source, char * dest, int mode, int uid, int gid) {
  function copy_file (line 49) | void copy_file(char * source, char * dest, int mode,int uid, int gid) {
  function copy_directory (line 80) | void copy_directory(char * source, char * dest, int mode, int uid, int g...
  function free_ramdisk (line 126) | void free_ramdisk(char * path) {
  function hashmap_t (line 133) | static hashmap_t * get_cmdline(void) {
  function root_is_tmpfs (line 139) | static int root_is_tmpfs(void) {
  function main (line 159) | int main(int argc, char * argv[]) {

FILE: apps/misaka-test.c
  function demo_runKurokoSnippet (line 20) | static void demo_runKurokoSnippet(void) {
  function demo_drawWallpaper (line 27) | static void demo_drawWallpaper(void) {
  function main (line 43) | int main(int argc, char * argv[]) {

FILE: apps/mixerctl.c
  function main (line 35) | int main(int argc, char * argv[]) {

FILE: apps/mkdir.c
  function makedir (line 18) | int makedir(const char * dir, int mask, int parents) {
  function main (line 40) | int main(int argc, char ** argv) {

FILE: apps/mktemp.c
  function main (line 17) | int main(int argc, char * argv[]) {

FILE: apps/more.c
  function to_eight (line 26) | static int to_eight(uint32_t codepoint, char * out) {
  function char_draw (line 61) | static void char_draw(int c) {
  function char_width (line 90) | static int char_width(int c) {
  type termios (line 107) | struct termios
  function get_initial_termios (line 108) | static void get_initial_termios(void) {
  function set_unbuffered (line 112) | static void set_unbuffered(void) {
  function set_buffered (line 119) | static void set_buffered(void) {
  function next_line (line 123) | static void next_line(void) {
  function do_file (line 156) | static void do_file(char * name, FILE * f) {
  function main (line 182) | int main(int argc, char * argv[]) {

FILE: apps/mount.c
  function main (line 15) | int main(int argc, char ** argv) {

FILE: apps/msk.c
  function release_lock (line 37) | static void release_lock(void) {
  function needs_lock (line 43) | static void needs_lock(void) {
  function compare_version_strings (line 63) | static int compare_version_strings(char * current, char * candidate) {
  function read_config (line 87) | static void read_config(void) {
  function read_manifest (line 101) | static void read_manifest(int required) {
  function read_installed (line 115) | static void read_installed(void) {
  function make_var (line 141) | static void make_var(void) {
  function needs_root (line 148) | static void needs_root(void) {
  function usage (line 155) | static int usage(int argc, char * argv[]) {
  function update_stores (line 170) | static int update_stores(int argc, char * argv[]) {
  function list_contains (line 268) | static int list_contains(list_t * list, char * key) {
  function process_package (line 276) | static int process_package(list_t * pkgs, char * name) {
  function install_package (line 307) | static int install_package(char * pkg) {
  function install_packages (line 435) | static int install_packages(int argc, char * argv[]) {
  function list_packages (line 479) | static int list_packages(int argc, char * argv[]) {
  function count_packages (line 497) | static int count_packages(int argc, char * argv[]) {
  function version (line 520) | static int version(void) {
  function main (line 525) | int main(int argc, char * argv[]) {

FILE: apps/mv.c
  function main (line 30) | int main(int argc, char * argv[]) {

FILE: apps/netty.c
  function main (line 47) | int main(int argc, char * argv[]) {

FILE: apps/nproc.c
  function main (line 12) | int main(int argc, char * argv[]) {

FILE: apps/nslookup.c
  function main (line 19) | int main(int argc, char * argv[]) {

FILE: apps/nyancat.c
  function digits (line 146) | int digits(int val) {
  function finish (line 178) | void finish() {
  function SIGINT_handler (line 191) | void SIGINT_handler(int sig){
  function SIGALRM_handler (line 200) | void SIGALRM_handler(int sig) {
  function SIGPIPE_handler (line 211) | void SIGPIPE_handler(int sig) {
  function SIGWINCH_handler (line 216) | void SIGWINCH_handler(int sig) {
  function newline (line 240) | void newline(int n) {
  function set_options (line 274) | void set_options() {
  function send_command (line 300) | void send_command(int cmd, int opt) {
  function usage (line 327) | void usage(char * argv[]) {
  function main (line 350) | int main(int argc, char ** argv) {

FILE: apps/package-manager.c
  type TT_Font (line 50) | struct TT_Font
  type TT_Font (line 51) | struct TT_Font
  type Package (line 53) | struct Package {
  type Package (line 62) | struct Package
  type menu_bar (line 65) | struct menu_bar
  type menu_bar_entries (line 66) | struct menu_bar_entries
  function _menu_action_exit (line 73) | static void _menu_action_exit(struct MenuEntry * entry) {
  function precise_current_time (line 83) | static uint64_t precise_current_time(void) {
  function precise_time_since (line 93) | static uint64_t precise_time_since(uint64_t start_time) {
  function _close_enough (line 101) | static int _close_enough(struct yutani_msg_window_mouse_event * me) {
  function draw_package (line 117) | static void draw_package(struct Package * package, int index) {
  function redraw_packages (line 153) | static void redraw_packages(void) {
  function load_manifest (line 161) | static void load_manifest(void) {
  type Package (line 246) | struct Package
  function clear_offset (line 253) | static void clear_offset(int offset) {
  function reinitialize_contents (line 257) | static void reinitialize_contents(void) {
  function redraw_window (line 279) | static void redraw_window(void) {
  function resize_finish (line 303) | static void resize_finish(int w, int h) {
  function _menu_action_refresh (line 336) | static void _menu_action_refresh(struct MenuEntry * entry) {
  function install_packages (line 357) | static void install_packages(void) {
  function _menu_action_about (line 385) | static void _menu_action_about(struct MenuEntry * entry) {
  function _menu_action_help (line 396) | static void _menu_action_help(struct MenuEntry * entry) {
  function toggle_selected (line 402) | static void toggle_selected(int hilighted_offset, int modifiers) {
  function _scroll_up (line 430) | static void _scroll_up(void) {
  function _scroll_down (line 437) | static void _scroll_down(void) {
  function arrow_select (line 448) | static void arrow_select(int y) {
  function redraw_window_callback (line 483) | static void redraw_window_callback(struct menu_bar * self) {
  function main (line 488) | int main(int argc, char * argv[]) {

FILE: apps/panel.c
  type PanelContext (line 62) | struct PanelContext
  type window_ad (line 85) | struct window_ad
  function _close_enough (line 94) | static int _close_enough(struct yutani_msg_window_mouse_event * me) {
  function center_x (line 101) | static int center_x(int x) {
  function center_y (line 105) | static int center_y(int y) {
  function center_x_a (line 109) | static int center_x_a(int x) {
  function center_x_a2 (line 113) | static int center_x_a2(int x) {
  function toggle_hide_panel (line 119) | static void toggle_hide_panel(void) {
  function sig_int (line 140) | static void sig_int(int sig) {
  function launch_application (line 146) | void launch_application(char * app) {
  function panel_check_click (line 156) | static void panel_check_click(struct yutani_msg_window_mouse_event * evt) {
  function close_altf2 (line 196) | static void close_altf2(void) {
  function redraw_altf2 (line 207) | static void redraw_altf2(void) {
  function redraw_alttab (line 220) | static void redraw_alttab(void) {
  function launch_application_menu (line 343) | void launch_application_menu(struct MenuEntry * self) {
  function handle_key_event (line 354) | static void handle_key_event(struct yutani_msg_key_event * ke) {
  function redraw (line 513) | void redraw(void) {
  function update_window_list (line 528) | static void update_window_list(void) {
  function redraw_panel_background (line 601) | static void redraw_panel_background(gfx_context_t * ctx, int width, int ...
  function resize_finish (line 605) | static void resize_finish(int xwidth, int xheight) {
  function bind_keys (line 624) | static void bind_keys(void) {
  function sig_usr2 (line 644) | static void sig_usr2(int sig) {
  function mouse_event_ignore (line 651) | static int mouse_event_ignore(struct PanelWidget * this, struct yutani_m...
  function widget_enter_generic (line 655) | static int widget_enter_generic(struct PanelWidget * this, struct yutani...
  function widget_leave_generic (line 660) | static int widget_leave_generic(struct PanelWidget * this, struct yutani...
  function panel_highlight_widget (line 665) | void panel_highlight_widget(struct PanelWidget * this, gfx_context_t * c...
  function widget_draw_generic (line 671) | static int widget_draw_generic(struct PanelWidget * this, gfx_context_t ...
  function widget_update_generic (line 684) | static int widget_update_generic(struct PanelWidget * this, int * force_...
  function widget_onkey_generic (line 688) | static int widget_onkey_generic(struct PanelWidget * this, struct yutani...
  type PanelWidget (line 692) | struct PanelWidget
  type PanelWidget (line 693) | struct PanelWidget
  type PanelWidget (line 693) | struct PanelWidget
  function widgets_layout (line 708) | static void widgets_layout(void) {
  function update_periodic_widgets (line 733) | static void update_periodic_widgets(int * force_updates) {
  function panel_menu_show_at (line 744) | int panel_menu_show_at(struct MenuList * menu, int x) {
  function panel_menu_show (line 772) | int panel_menu_show(struct PanelWidget * this, struct MenuList * menu) {
  function main (line 776) | int main (int argc, char ** argv) {

FILE: apps/piano.c
  type spkr (line 17) | struct spkr {
  function note (line 22) | void note(int length, int frequency) {
  type termios (line 31) | struct termios
  function set_unbuffered (line 33) | void set_unbuffered() {
  function main (line 41) | int main(int argc, char * argv[]) {

FILE: apps/pidof.c
  type p_t (line 18) | typedef struct process {
  function p_t (line 28) | p_t * build_entry(struct dirent * dent) {
  function main (line 85) | int main (int argc, char * argv[]) {

FILE: apps/ping.c
  type ICMP_Header (line 27) | struct ICMP_Header {
  function clocktime (line 35) | static unsigned long clocktime(void) {
  function icmp_checksum (line 41) | static uint16_t icmp_checksum(char * payload, size_t len) {
  function sig_break_loop (line 55) | static void sig_break_loop(int sig) {
  function main (line 60) | int main(int argc, char * argv[]) {

FILE: apps/plasma.c
  function sigint_handler (line 42) | void sigint_handler() {
  function redraw_borders (line 48) | void redraw_borders() {
  function hsv_to_rgb (line 52) | uint32_t hsv_to_rgb(int h, float s, float v) {
  function resize_finish (line 102) | void resize_finish(int w, int h) {
  function main (line 117) | int main (int argc, char ** argv) {

FILE: apps/play.c
  function usage (line 27) | static int usage(char * argv[]) {
  function main (line 32) | int main(int argc, char * argv[]) {

FILE: apps/polygons.c
  type coord (line 32) | struct coord {
  type edge (line 37) | struct edge {
  type contour (line 43) | struct contour {
  type intersection (line 51) | struct intersection {
  type shape (line 56) | struct shape {
  function edge_sorter_high_scanline (line 62) | static int edge_sorter_high_scanline(const void * a, const void * b) {
  function sort_edges (line 71) | static void sort_edges(size_t edgeCount, struct edge edges[edgeCount]) {
  function intersection_sorter (line 75) | static int intersection_sorter(const void * a, const void * b) {
  function sort_intersections (line 84) | static void sort_intersections(size_t cnt, struct intersection intersect...
  function prune_edges (line 88) | static size_t prune_edges(size_t edgeCount, float y, struct edge edges[e...
  function edge_at (line 98) | static float edge_at(float y, struct edge * edge) {
  type shape (line 103) | struct shape
  type contour (line 103) | struct contour
  type shape (line 105) | struct shape
  type shape (line 105) | struct shape
  type edge (line 105) | struct edge
  type edge (line 106) | struct edge
  type coord (line 122) | struct coord
  function path_paint (line 138) | void path_paint(gfx_context_t * ctx, struct shape * shape, uint32_t colo...
  type contour (line 203) | struct contour
  type shape (line 204) | struct shape
  function add_point (line 207) | static void add_point(float x, float y) {
  function move_to (line 230) | static void move_to(float x, float y) {
  function draw (line 250) | static void draw(void) {
  function finish_draw (line 265) | static void finish_draw(void) {
  function main (line 270) | int main (int argc, char ** argv) {

FILE: apps/pong.c
  type object (line 42) | struct object {
  type object (line 56) | struct object
  type object (line 57) | struct object
  type object (line 58) | struct object
  type spkr (line 69) | struct spkr {
  function note (line 74) | static void note(int frequency) {
  function current_time (line 84) | static uint32_t current_time() {
  function colliding (line 107) | static int colliding(struct object * a, struct object * b) {
  function redraw (line 116) | void redraw(void) {
  function update_left (line 130) | void update_left(void) {
  function update_right (line 133) | void update_right(void) {
  function update_ball (line 136) | void update_ball(void) {
  function update_stuff (line 140) | void update_stuff(void) {
  function main (line 199) | int main (int argc, char ** argv) {

FILE: apps/ps.c
  type process (line 39) | struct process {
  function print_username (line 54) | void print_username(int uid) {
  type process (line 66) | struct process
  type process (line 70) | struct process
  type dirent (line 70) | struct dirent
  type process (line 127) | struct process
  type process (line 136) | struct process
  type process (line 136) | struct process
  type passwd (line 164) | struct passwd
  function print_header (line 195) | void print_header(void) {
  function print_entry (line 217) | void print_entry(struct process * out) {
  function show_usage (line 259) | void show_usage(int argc, char * argv[]) {
  function main (line 276) | int main (int argc, char * argv[]) {

FILE: apps/pstree.c
  type p_t (line 21) | typedef struct process {
  function p_t (line 31) | p_t * build_entry(struct dirent * dent) {
  function find_pid (line 88) | uint8_t find_pid(void * proc_v, void * pid_v) {
  function print_process_tree_node (line 95) | void print_process_tree_node(tree_node_t * node, size_t depth, int inden...
  function main (line 148) | int main (int argc, char * argv[]) {

FILE: apps/pwd.c
  function main (line 12) | int main(int argc, char * argv[]) {

FILE: apps/qemu-display-hack.c
  function main (line 26) | int main(int argc, char * argv[]) {

FILE: apps/qemu-fwcfg.c
  function outports (line 33) | static void outports(unsigned short _port, unsigned short _data) {
  function inportb (line 37) | static unsigned char inportb(unsigned short _port) {
  function swap_bytes (line 44) | static void swap_bytes(void * in, int count) {
  type fw_cfg_file (line 56) | struct fw_cfg_file {
  function usage (line 63) | static int usage(char * argv[]) {
  function sig_pass (line 76) | static void sig_pass(int sig) {
  function main (line 80) | int main(int argc, char * argv[]) {

FILE: apps/readelf.c
  function CASE (line 300) | CASE(R_X86_64_NONE)
  function usage (line 391) | static int usage(char * argv[]) {
  type StringTable (line 413) | struct StringTable {
  type StringTable (line 418) | struct StringTable
  type StringTable (line 419) | struct StringTable
  type StringTable (line 419) | struct StringTable
  type StringTable (line 427) | struct StringTable
  function main (line 432) | int main(int argc, char * argv[]) {

FILE: apps/readlink.c
  function main (line 18) | int main(int argc, char * argv[]) {

FILE: apps/reboot.c
  function main (line 15) | int main(int argc, char ** argv) {

FILE: apps/reset.c
  function main (line 14) | int main(int argc, char * argv[]) {

FILE: apps/rm.c
  function rm_directory (line 28) | static int rm_directory(char * source) {
  function rm_thing (line 58) | static int rm_thing(char * tmp) {
  function rm_top_level (line 78) | static int rm_top_level(char **argv, int argc, int optind) {
  function main (line 88) | int main(int argc, char * argv[]) {

FILE: apps/rmdir.c
  function usage (line 15) | static int usage(char * argv[]) {
  function main (line 30) | int main(int argc, char * argv[]) {

FILE: apps/serial-console.c
  type termios (line 28) | struct termios
  function set_unbuffered (line 30) | void set_unbuffered() {
  function set_buffered (line 42) | void set_buffered() {
  function show_usage (line 46) | int show_usage(int argc, char * argv[]) {
  function main (line 60) | int main(int argc, char ** argv) {

FILE: apps/session.c
  function main (line 19) | int main(int argc, char * argv[]) {

FILE: apps/set-resolution.c
  function main (line 19) | int main(int argc, char * argv[]) {

FILE: apps/showdialog.c
  type TT_Font (line 34) | struct TT_Font
  function draw_string (line 36) | static void draw_string(int y, const char * string, uint32_t color) {
  type TTKButton (line 45) | struct TTKButton
  type TTKButton (line 46) | struct TTKButton
  function redraw (line 48) | static void redraw(void) {
  function init_default (line 79) | static void init_default(void) {
  function in_button (line 87) | int in_button(struct TTKButton * button, struct yutani_msg_window_mouse_...
  function setup_buttons (line 96) | void setup_buttons(void) {
  function resize_finish (line 113) | void resize_finish(int w, int h) {
  function set_hilight (line 123) | void set_hilight(struct TTKButton * button, int hilight) {
  function main (line 137) | int main(int argc, char * argv[]) {

FILE: apps/sleep.c
  function main (line 14) | int main(int argc, char ** argv) {

FILE: apps/snow.c
  function add_flake (line 42) | static void add_flake() {
  function draw (line 56) | static void draw(void) {
  function resize_finish (line 78) | void resize_finish(int w, int h) {
  function precise_current_time (line 87) | static uint64_t precise_current_time(void) {
  function precise_time_since (line 97) | static uint64_t precise_time_since(uint64_t start_time) {
  function main (line 105) | int main (int argc, char ** argv) {

FILE: apps/sort.c
  function compare (line 21) | int compare(const char * a, const char * b) {
  function main (line 39) | int main(int argc, char * argv[]) {

FILE: apps/splash-log.c
  function update_message (line 46) | static void update_message(char * c) {
  function open_socket (line 51) | static void open_socket(void) {
  function say_hello (line 56) | static void say_hello(void) {
  function hashmap_t (line 71) | static hashmap_t * get_cmdline(void) {
  function main (line 77) | int main(int argc, char * argv[]) {

FILE: apps/stat.c
  function show_usage (line 22) | static void show_usage(int argc, char * argv[]) {
  function stat_file (line 36) | static int stat_file(char * file) {
  function main (line 99) | int main(int argc, char ** argv) {

FILE: apps/strace.c
  function open_flags (line 386) | static void open_flags(int flags) {
  function string_arg (line 413) | static void string_arg(pid_t pid, uintptr_t ptr) {
  function pointer_arg (line 450) | static void pointer_arg(uintptr_t ptr) {
  function uint_arg (line 455) | static void uint_arg(size_t val) {
  function int_arg (line 459) | static void int_arg(size_t val) {
  function mode_arg (line 463) | static void mode_arg(mode_t val) {
  function fd_arg (line 467) | static void fd_arg(pid_t pid, int val) {
  function sock_dom_arg (line 472) | static void sock_dom_arg(int domain) {
  function sock_typ_arg (line 481) | static void sock_typ_arg(int type) {
  function sock_pro_arg (line 490) | static void sock_pro_arg(int domain, int type, int proto) {
  function sock_lvl_arg (line 509) | static void sock_lvl_arg(int level) {
  function sock_opt_arg (line 516) | static void sock_opt_arg(int opt) {
  function data_read_bytes (line 525) | static int data_read_bytes(pid_t pid, uintptr_t addr, char * buf, size_t...
  function data_read_int (line 534) | static int data_read_int(pid_t pid, uintptr_t addr) {
  function data_read_ptr (line 540) | static uintptr_t data_read_ptr(pid_t pid, uintptr_t addr) {
  function sockaddr_arg (line 546) | static void sockaddr_arg(pid_t pid, uintptr_t addr, size_t size) {
  function sockaddrp_arg (line 567) | static void sockaddrp_arg(pid_t pid, uintptr_t addr, uintptr_t size_p) {
  function fds_arg (line 574) | static void fds_arg(pid_t pid, size_t ecount, uintptr_t array) {
  function string_array_arg (line 585) | static void string_array_arg(pid_t pid, uintptr_t array) {
  function buffer_arg (line 598) | static void buffer_arg(pid_t pid, uintptr_t buffer, ssize_t count) {
  function msghdr_arg (line 626) | static void msghdr_arg(pid_t pid, uintptr_t msghdr) {
  function fcntl_cmd_arg (line 644) | static void fcntl_cmd_arg(long cmd) {
  function print_error (line 653) | static void print_error(int err) {
  function maybe_errno (line 662) | static void maybe_errno(struct URegs * r) {
  function struct_utsname_arg (line 668) | static void struct_utsname_arg(pid_t pid, uintptr_t ptr) {
  function struct_timeval_arg (line 684) | static void struct_timeval_arg(pid_t pid, uintptr_t ptr) {
  function signal_arg (line 699) | static void signal_arg(int signum) {
  function sigset_ptr_arg (line 707) | static void sigset_ptr_arg(pid_t pid, uintptr_t ptr) {
  function signal_ptr_arg (line 741) | static void signal_ptr_arg(pid_t pid, uintptr_t ptr) {
  function handle_syscall (line 748) | static void handle_syscall(pid_t pid, struct URegs * r) {
  function finish_syscall (line 1072) | static void finish_syscall(pid_t pid, int syscall, struct URegs * r) {
  function usage (line 1135) | static int usage(char * argv[]) {
  function main (line 1147) | int main(int argc, char * argv[]) {

FILE: apps/strings.c
  function read_file (line 20) | static void read_file(FILE * f) {
  function main (line 59) | int main(int argc, char * argv[]) {

FILE: apps/stty.c
  function print_cc (line 25) | static void print_cc(struct termios * t, const char * lbl, int val, int ...
  function print_ (line 40) | static void print_(int flags, const char * lbl, int val, int def) {
  function set_char_ (line 53) | static int set_char_(struct termios *t, const char * lbl, int val, const...
  function setunset_flag (line 85) | static int setunset_flag(tcflag_t * flag, const char * lbl, int val, con...
  function set_toggle_ (line 105) | static int set_toggle_(tcflag_t * flag, const char * lbl, int base, int ...
  type baud_table (line 117) | struct baud_table {
  function set_baud_rate (line 145) | static int set_baud_rate(struct termios * t, const char * arg) {
  function print_baud_rate (line 155) | static int print_baud_rate(struct termios * t) {
  function show_settings (line 166) | static int show_settings(int all) {
  function show_size (line 288) | static void show_size(void) {
  function main (line 294) | int main(int argc, char * argv[]) {

FILE: apps/sudo.c
  function sudo_loop (line 37) | static int sudo_loop(int (*prompt_callback)(char * username, char * pass...
  function basic_callback (line 170) | static int basic_callback(char * username, char * password, int fails, c...
  function usage (line 191) | void usage(int argc, char * argv[]) {
  function main (line 195) | int main(int argc, char ** argv) {

FILE: apps/sync.c
  function main (line 25) | int main(int argc, char * argv[]) {

FILE: apps/sysfunc.c
  function main (line 19) | int main(int argc, char ** argv) {

FILE: apps/sysinfo.c
  function print_thing (line 49) | void print_thing(int j) {
  function reset (line 59) | static void reset(void) {
  function foreground_color (line 64) | static void foreground_color(uint32_t color) {
  function background_color (line 69) | static void background_color(uint32_t color) {
  function main (line 74) | int main(int argc, char * argv[]) {

FILE: apps/t_mbstowcs.c
  function main (line 13) | int main(int argc, char * argv[]) {

FILE: apps/tar.c
  type ustar (line 26) | struct ustar {
  type ustar (line 52) | struct ustar
  type ustar (line 53) | struct ustar
  type ustar (line 54) | struct ustar
  type ustar (line 54) | struct ustar
  function interpret_mode (line 66) | static unsigned int interpret_mode(struct ustar * file) {
  function interpret_size (line 77) | static unsigned int interpret_size(struct ustar * file) {
  function dump_file (line 124) | static void dump_file(struct ustar * file) {
  function write_file (line 132) | static void write_file(struct ustar * file, FILE * f, FILE * mf, char * ...
  function _seek_forward (line 151) | static void _seek_forward(FILE * f, size_t amount) {
  function usage (line 157) | static void usage(char * argv[]) {
  function matches_files (line 168) | static int matches_files(int argc, char * argv[], int optind, char * fil...
  function main (line 177) | int main(int argc, char * argv[]) {

FILE: apps/tee.c
  function main (line 17) | int main(int argc, char * argv[]) {

FILE: apps/terminal-vga.c
  function get_ticks (line 92) | static uint64_t get_ticks(void) {
  function color_distance (line 99) | static int color_distance(uint32_t a, uint32_t b) {
  function is_gray (line 136) | static int is_gray(uint32_t a) {
  function best_match (line 145) | static int best_match(uint32_t a) {
  function min (line 162) | uint16_t min(uint16_t a, uint16_t b) {
  function max (line 167) | uint16_t max(uint16_t a, uint16_t b) {
  function set_title (line 171) | void set_title(char * c) {
  function is_in_selection (line 178) | int is_in_selection(int x, int y) {
  function iterate_selection (line 209) | void iterate_selection(void (*func)(uint16_t x, uint16_t y)) {
  function redraw_selection (line 249) | void redraw_selection(void) {
  function term_cell_t (line 253) | static term_cell_t * cell_at(uint16_t x, uint16_t y) {
  function mark_cell (line 257) | static void mark_cell(uint16_t x, uint16_t y) {
  function mark_selection (line 264) | static void mark_selection(void) {
  function red_cell (line 268) | static void red_cell(uint16_t x, uint16_t y) {
  function flip_selection (line 279) | static void flip_selection(void) {
  function to_eight (line 296) | static int to_eight(uint32_t codepoint, char * out) {
  function count_selection (line 331) | void count_selection(uint16_t x, uint16_t y) {
  function write_selection (line 342) | void write_selection(uint16_t x, uint16_t y) {
  type input_data (line 387) | struct input_data {
  type input_data (line 411) | struct input_data
  function write_input_buffer (line 424) | static void write_input_buffer(char * data, size_t len) {
  function handle_input (line 434) | void handle_input(char c) {
  function handle_input_s (line 438) | void handle_input_s(char * c) {
  function placech (line 446) | void placech(unsigned char c, int x, int y, int attr) {
  function maybe_write_screen (line 452) | static void maybe_write_screen(void) {
  function term_write_char (line 470) | void
  function cell_set (line 498) | static void cell_set(uint16_t x, uint16_t y, uint32_t c, uint32_t fg, ui...
  function cell_redraw (line 507) | static void cell_redraw(uint16_t x, uint16_t y) {
  function cell_redraw_inverted (line 517) | static void cell_redraw_inverted(uint16_t x, uint16_t y) {
  function cell_redraw_box (line 528) | static void cell_redraw_box(uint16_t x, uint16_t y) {
  function render_cursor (line 539) | void render_cursor() {
  function draw_cursor (line 545) | void draw_cursor() {
  function term_redraw_all (line 552) | void term_redraw_all() {
  function term_shift_region (line 561) | void term_shift_region(int top, int height, int how_much) {
  function term_scroll (line 599) | void term_scroll(int how_much) {
  function insert_delete_lines (line 603) | void insert_delete_lines(int how_many) {
  function is_wide (line 614) | int is_wide(uint32_t codepoint) {
  function undraw_cursor (line 619) | static void undraw_cursor(void) {
  function normalize_x (line 623) | static void normalize_x(int setting_lcf) {
  function normalize_y (line 632) | static void normalize_y(void) {
  function term_write (line 640) | void term_write(char c) {
  function term_set_csr (line 723) | void term_set_csr(int x, int y) {
  function term_get_csr_x (line 735) | int term_get_csr_x() {
  function term_get_csr_y (line 739) | int term_get_csr_y() {
  function term_set_csr_show (line 743) | void term_set_csr_show(int on) {
  function term_set_colors (line 750) | void term_set_colors(uint32_t fg, uint32_t bg) {
  function term_redraw_cursor (line 755) | void term_redraw_cursor() {
  function flip_cursor (line 761) | void flip_cursor() {
  function term_set_cell (line 770) | void term_set_cell(int x, int y, uint32_t c) {
  function term_redraw_cell (line 775) | void term_redraw_cell(int x, int y) {
  function term_clear (line 780) | void term_clear(int i) {
  function key_event (line 811) | void key_event(int ret, key_event_t * event) {
  function usage (line 978) | void usage(char * argv[]) {
  function unsupported_int (line 989) | int unsupported_int(void) { return 0; }
  function unsupported (line 990) | void unsupported(int x, int y, char * data) { }
  function term_switch_buffer (line 993) | static void term_switch_buffer(int buffer) {
  function full_reset (line 1008) | static void full_reset(void) {
  function reinit (line 1055) | void reinit(void) {
  function maybe_flip_cursor (line 1077) | void maybe_flip_cursor(void) {
  function check_for_exit (line 1086) | void check_for_exit(void) {
  function mouse_event (line 1112) | static void mouse_event(int button, int x, int y) {
  function redraw_mouse (line 1124) | static void redraw_mouse(void) {
  function handle_mouse_event (line 1145) | void handle_mouse_event(mouse_device_packet_t * packet) {
  function handle_mouse (line 1227) | void handle_mouse(mouse_device_packet_t * packet) {
  function handle_mouse_abs (line 1237) | void handle_mouse_abs(mouse_device_packet_t * packet) {
  function sig_suspend_input (line 1249) | void sig_suspend_input(int sig) {
  function main (line 1259) | int main(int argc, char ** argv) {

FILE: apps/terminal.c
  function usage (line 55) | static void usage(char * argv[]) {
  type TT_Font (line 115) | struct TT_Font
  type TT_Font (line 116) | struct TT_Font
  type TT_Font (line 117) | struct TT_Font
  type TT_Font (line 118) | struct TT_Font
  type TT_Font (line 120) | struct TT_Font
  type TT_Font (line 121) | struct TT_Font
  type MenuList (line 161) | struct MenuList
  type scrollback_row (line 175) | struct scrollback_row {
  type menu_bar (line 185) | struct menu_bar
  type menu_bar_entries (line 186) | struct menu_bar_entries
  type MenuEntry (line 195) | struct MenuEntry
  type MenuEntry (line 196) | struct MenuEntry
  type MenuEntry (line 197) | struct MenuEntry
  type MenuEntry (line 198) | struct MenuEntry
  type MenuEntry (line 199) | struct MenuEntry
  type MenuEntry (line 200) | struct MenuEntry
  type MenuEntry (line 201) | struct MenuEntry
  type MenuEntry (line 202) | struct MenuEntry
  type MenuEntry (line 203) | struct MenuEntry
  type MenuEntry (line 204) | struct MenuEntry
  function get_ticks (line 217) | static uint64_t get_ticks(void) {
  function display_flip (line 224) | static void display_flip(void) {
  function min (line 236) | static int32_t min(int32_t a, int32_t b) {
  function max (line 241) | static int32_t max(int32_t a, int32_t b) {
  function to_eight (line 250) | static int to_eight(uint32_t codepoint, char * out) {
  function set_title (line 286) | static void set_title(char * c) {
  function iterate_selection (line 295) | static void iterate_selection(void (*func)(uint16_t x, uint16_t y)) {
  function redraw_selection (line 336) | static void redraw_selection(void) {
  function term_cell_t (line 340) | static term_cell_t * cell_at(uint16_t x, uint16_t _y) {
  function mark_cell (line 361) | static void mark_cell(uint16_t x, uint16_t y) {
  function mark_selection (line 368) | static void mark_selection(void) {
  function red_cell (line 372) | static void red_cell(uint16_t x, uint16_t y) {
  function flip_selection (line 383) | static void flip_selection(void) {
  function count_selection (line 398) | static void count_selection(uint16_t x, uint16_t _y) {
  function write_selection (line 432) | void write_selection(uint16_t x, uint16_t _y) {
  type input_data (line 505) | struct input_data {
  type input_data (line 529) | struct input_data
  function write_input_buffer (line 542) | static void write_input_buffer(char * data, size_t len) {
  function input_buffer_stuff (line 554) | static void input_buffer_stuff(char * str) {
  function render_decors (line 561) | static void render_decors(void) {
  function term_set_point (line 592) | static inline void term_set_point(uint16_t x, uint16_t y, uint32_t color...
  function _fill_region (line 596) | static void _fill_region(uint32_t _bg, uint16_t x, uint16_t y, uint16_t ...
  function draw_semi_block (line 605) | static void draw_semi_block(int c, int x, int y, uint32_t fg, uint32_t b...
  function draw_box_drawing (line 634) | static void draw_box_drawing(int c, int x, int y, uint32_t fg, uint32_t ...
  type GlyphCacheEntry (line 678) | struct GlyphCacheEntry {
  type GlyphCacheEntry (line 686) | struct GlyphCacheEntry
  function _menu_action_cache_stats (line 691) | static void _menu_action_cache_stats(struct MenuEntry * self) {
  function _menu_action_clear_cache (line 715) | static void _menu_action_clear_cache(struct MenuEntry * self) {
  function draw_cached_glyph (line 724) | static void draw_cached_glyph(gfx_context_t * ctx, struct TT_Font * _fon...
  function term_write_char (line 758) | static void term_write_char(uint32_t val, uint16_t x, uint16_t y, uint32...
  function term_mirror_set (line 926) | static void term_mirror_set(uint16_t x, uint16_t y, uint32_t val, uint32...
  function term_mirror_copy (line 935) | static void term_mirror_copy(uint16_t x, uint16_t y, term_cell_t * from) {
  function term_mirror_copy_inverted (line 948) | static void term_mirror_copy_inverted(uint16_t x, uint16_t y, term_cell_...
  function cell_set (line 970) | static void cell_set(uint16_t x, uint16_t y, uint32_t c, uint32_t fg, ui...
  function redraw_cell_image (line 985) | static void redraw_cell_image(uint16_t x, uint16_t y, term_cell_t * cell...
  function maybe_flip_display (line 1016) | static void maybe_flip_display(int force) {
  function cell_redraw_offset (line 1044) | static void cell_redraw_offset(uint16_t x, uint16_t _y) {
  function cell_redraw_offset_inverted (line 1069) | static void cell_redraw_offset_inverted(uint16_t x, uint16_t _y) {
  function cell_redraw (line 1095) | static void cell_redraw(uint16_t x, uint16_t y) {
  function cell_redraw_inverted (line 1101) | static void cell_redraw_inverted(uint16_t x, uint16_t y) {
  function cell_redraw_box (line 1108) | static void cell_redraw_box(uint16_t x, uint16_t y) {
  function render_cursor (line 1116) | static void render_cursor() {
  function draw_cursor (line 1129) | static void draw_cursor() {
  function maybe_flip_cursor (line 1136) | static void maybe_flip_cursor(void) {
  function term_redraw_all (line 1153) | static void term_redraw_all() {
  function _menu_action_redraw (line 1161) | static void _menu_action_redraw(struct MenuEntry * self) {
  function flush_unused_images (line 1166) | static void flush_unused_images(void) {
  function term_shift_region (line 1215) | static void term_shift_region(int top, int height, int how_much) {
  function term_scroll (line 1258) | static void term_scroll(int how_much) {
  function insert_delete_lines (line 1265) | static void insert_delete_lines(int how_many) {
  function is_wide (line 1277) | static int is_wide(uint32_t codepoint) {
  function save_scrollback (line 1283) | static void save_scrollback(void) {
  function redraw_scrollback (line 1316) | static void redraw_scrollback(void) {
  function undraw_cursor (line 1374) | static void undraw_cursor(void) {
  function normalize_x (line 1378) | static void normalize_x(int setting_lcf) {
  function normalize_y (line 1387) | static void normalize_y(void) {
  function term_write (line 1400) | static void term_write(char c) {
  function term_set_csr (line 1485) | static void term_set_csr(int x, int y) {
  function term_get_csr_x (line 1498) | static int term_get_csr_x(void) {
  function term_get_csr_y (line 1503) | static int term_get_csr_y(void) {
  function term_set_cell_contents (line 1508) | static void term_set_cell_contents(int x, int y, char * data) {
  function term_get_cell_width (line 1519) | static int term_get_cell_width(void) {
  function term_get_cell_height (line 1524) | static int term_get_cell_height(void) {
  function term_set_csr_show (line 1529) | static void term_set_csr_show(int on) {
  function term_set_colors (line 1537) | static void term_set_colors(uint32_t fg, uint32_t bg) {
  function term_redraw_cursor (line 1543) | static void term_redraw_cursor() {
  function term_set_cell (line 1550) | static void term_set_cell(int x, int y, uint32_t c) {
  function term_clear (line 1556) | static void term_clear(int i) {
  function term_switch_buffer (line 1605) | static void term_switch_buffer(int buffer) {
  function full_reset (line 1620) | static void full_reset(void) {
  function handle_input (line 1674) | static void handle_input(char c) {
  function handle_input_s (line 1682) | static void handle_input_s(char * c) {
  function scroll_up (line 1693) | static void scroll_up(int amount) {
  function scroll_down (line 1703) | void scroll_down(int amount) {
  function key_event (line 1713) | static void key_event(int ret, key_event_t * event) {
  function check_for_exit (line 1942) | static void check_for_exit(void) {
  function term_cell_t (line 1961) | static term_cell_t * copy_terminal(int old_width, int old_height, term_c...
  function reinit (line 1989) | static void reinit(void) {
  function update_bounds (line 2071) | static void update_bounds(void) {
  function resize_finish (line 2095) | static void resize_finish(int width, int height) {
  function mouse_event (line 2144) | static void mouse_event(int button, int x, int y) {
  type yutani_msg_key_event (line 2169) | struct yutani_msg_key_event
  type yutani_msg_window_focus_change (line 2176) | struct yutani_msg_window_focus_change
  type yutani_msg_window_close (line 2188) | struct yutani_msg_window_close
  type yutani_msg_window_resize (line 2203) | struct yutani_msg_window_resize
  type yutani_msg_clipboard (line 2209) | struct yutani_msg_clipboard
  type yutani_msg_window_mouse_event (line 2236) | struct yutani_msg_window_mouse_event
  function _menu_action_exit (line 2406) | static void _menu_action_exit(struct MenuEntry * self) {
  function _menu_action_hide_borders (line 2411) | static void _menu_action_hide_borders(struct MenuEntry * self) {
  type MenuEntry (line 2422) | struct MenuEntry
  type MenuEntry (line 2423) | struct MenuEntry
  function _menu_action_toggle_tt (line 2425) | static void _menu_action_toggle_tt(struct MenuEntry * self) {
  function _menu_action_toggle_free_size (line 2433) | static void _menu_action_toggle_free_size(struct MenuEntry * self) {
  function _menu_action_show_about (line 2438) | static void _menu_action_show_about(struct MenuEntry * self) {
  function _menu_action_show_help (line 2448) | static void _menu_action_show_help(struct MenuEntry * self) {
  function _menu_action_copy (line 2453) | static void _menu_action_copy(struct MenuEntry * self) {
  function _menu_action_paste (line 2457) | static void _menu_action_paste(struct MenuEntry * self) {
  function update_scale_menu (line 2461) | static void update_scale_menu(void) {
  function _menu_action_set_scale (line 2468) | static void _menu_action_set_scale(struct MenuEntry * self) {
  function render_decors_callback (line 2482) | static void render_decors_callback(struct menu_bar * self) {
  function parse_geometry (line 2494) | static void parse_geometry(char ** argv, char * str) {
  function main (line 2532) | int main(int argc, char ** argv) {

FILE: apps/test-badwrite.c
  function main (line 13) | int main(int argc, char * argv[]) {

FILE: apps/test-conf.c
  function main (line 14) | int main(int argc, char * argv[]) {

FILE: apps/test-fpclassify.c
  function main (line 7) | int main(int argc, char * argv[]) {

FILE: apps/test-ftruncate.c
  function main (line 16) | int main(int argc, char * argv[]) {

FILE: apps/test-localtime.c
  function main (line 12) | int main(int argc, char * argv[]) {

FILE: apps/test-lock.c
  function main (line 15) | int main(int argc, char * argv[]) {

FILE: apps/test-loop.c
  function main (line 9) | int main(int argc, char * argv[]) {

FILE: apps/test-printf.c
  function main (line 11) | int main(int argc, char * argv[]) {

FILE: apps/test-ptrace-syscall.c
  function main (line 19) | int main(int argc, char * argv[]) {

FILE: apps/test-sigsegv.c
  function main (line 16) | int main(int argc, char * argv[]) {

FILE: apps/test-sigsuspend.c
  function handler (line 7) | void handler(int sig) {
  function main (line 11) | int main(int argc, char * argv[]) {

FILE: apps/test-sigwait.c
  function handler (line 6) | void handler(int sig) {
  function main (line 10) | int main(int argc, char * argv[]) {

FILE: apps/test-syscall-sysret.c
  function main (line 5) | int main(int argc, char * argv[]){

FILE: apps/test-tls.c
  function main (line 26) | int main(int argc, char * argv[]) {

FILE: apps/test-tty-read.c
  type termios (line 7) | struct termios
  type termios (line 8) | struct termios
  function get_initial_termios (line 9) | void get_initial_termios(void) {
  function on_sigusr1 (line 13) | void on_sigusr1(int sig) {
  function set_unbuffered (line 19) | void set_unbuffered(void) {
  function set_buffered (line 30) | void set_buffered(void) {
  function main (line 34) | int main(int argc, char * argv[]) {

FILE: apps/toastd.c
  type JSON_Value (line 26) | typedef struct JSON_Value JSON_Value;
  type ToastNotification (line 34) | struct ToastNotification {
  function handle_msg (line 43) | static void handle_msg(JSON_Value * msg) {
  function main (line 115) | int main(int argc, char * argv[]) {

FILE: apps/toggle-abs-mouse.c
  function main (line 19) | int main(int argc, char * argv[]) {

FILE: apps/top.c
  type header_columns (line 32) | enum header_columns {
  type process (line 67) | struct process {
  type columns (line 75) | struct columns {
  type process (line 83) | struct process
  type process (line 84) | struct process
  type process (line 85) | struct process
  type process (line 86) | struct process
  type process (line 87) | struct process
  type process (line 88) | struct process
  type process (line 89) | struct process
  type process (line 90) | struct process
  type process (line 91) | struct process
  function print_column (line 99) | static int print_column(struct process * proc, int column_id) {
  function size_column (line 125) | static int size_column(struct process * proc, int column_id) {
  function print_header (line 152) | void print_header(void) {
  function reset_column_widths (line 170) | void reset_column_widths(void) {
  function print_entry (line 182) | void print_entry(struct process * out, int width) {
  function update_column_widths (line 195) | void update_column_widths(struct process * out) {
  function free_entry (line 208) | void free_entry(struct process * out) {
  type passwd (line 225) | struct passwd
  type process (line 242) | struct process
  type process (line 252) | struct process
  type dirent (line 252) | struct dirent
  type process (line 308) | struct process
  type process (line 316) | struct process
  type process (line 316) | struct process
  function sort_processes (line 357) | static int sort_processes(const void * a, const void * b) {
  function get_mem_info (line 389) | static void get_mem_info(int * total, int * used) {
  function get_cpu_info (line 418) | static void get_cpu_info(int cpus[]) {
  function get_tmpfs_info (line 439) | static void get_tmpfs_info(size_t * size) {
  function print_meter (line 469) | static void print_meter(const char * title, const char * label, int widt...
  function next_sort_order (line 513) | static void next_sort_order(void) {
  function prev_sort_order (line 526) | static void prev_sort_order(void) {
  type process (line 539) | struct process
  type dirent (line 549) | struct dirent
  type process (line 552) | struct process
  type process (line 567) | struct process
  type process (line 567) | struct process
  type process (line 578) | struct process
  function do_once (line 586) | static int do_once(void) {
  function do_log (line 731) | static int do_log(void) {
  type termios (line 794) | struct termios
  function get_initial_termios (line 795) | void get_initial_termios(void) {
  function set_unbuffered (line 802) | void set_unbuffered(void) {
  function set_buffered (line 813) | void set_buffered(void) {
  function SIGWINCH_handler (line 818) | void SIGWINCH_handler(int sig) {
  function main (line 823) | int main (int argc, char * argv[]) {

FILE: apps/touch.c
  function main (line 13) | int main(int argc, char * argv[]) {

FILE: apps/true.c
  function main (line 9) | int main() {

FILE: apps/tty.c
  function main (line 12) | int main(int argc, char * argv[]) {

FILE: apps/ttysize.c
  type termios (line 25) | struct termios
  function set_unbuffered (line 27) | static void set_unbuffered() {
  function set_buffered (line 34) | static void set_buffered() {
  function getc_timeout (line 38) | static int getc_timeout(int timeout) {
  function divine_size (line 50) | static void divine_size(int * width, int * height) {
  function main (line 83) | int main(int argc, char * argv[]) {

FILE: apps/tutorial.c
  type TT_Font (line 47) | struct TT_Font
  type TT_Font (line 48) | struct TT_Font
  function center (line 52) | static int center(int x, int width) {
  function draw_string (line 56) | static void draw_string(int y, const char * string, struct TT_Font * fon...
  type TTKButton (line 65) | struct TTKButton
  type TTKButton (line 66) | struct TTKButton
  function redraw (line 70) | static void redraw(void) {
  function reset_background (line 114) | static void reset_background(void) {
  function invert_background_alpha (line 118) | static void invert_background_alpha(void) {
  function circle (line 132) | static void circle(int x, int y, int r) {
  function load_page (line 150) | static void load_page(int page) {
  function in_button (line 259) | int in_button(struct TTKButton * button, struct yutani_msg_window_mouse_...
  function setup_buttons (line 268) | void setup_buttons(void) {
  function update_size (line 285) | static void update_size(int w, int h) {
  function resize_finish (line 292) | void resize_finish(int w, int h) {
  function resize_finish_bg (line 301) | void resize_finish_bg(int w, int h) {
  function set_hilight (line 308) | void set_hilight(struct TTKButton * button, int hilight) {
  function main (line 322) | int main(int argc, char * argv[]) {

FILE: apps/uname.c
  function show_usage (line 33) | void show_usage(int argc, char * argv[]) {
  function main (line 51) | int main(int argc, char * argv[]) {

FILE: apps/ununicode.h
  function ununicode (line 2) | static uint32_t ununicode(uint32_t c) {

FILE: apps/uptime.c
  function print_time (line 16) | void print_time(void) {
  function print_seconds (line 31) | void print_seconds(int seconds) {
  function print_uptime (line 52) | void print_uptime(void) {
  function show_usage (line 72) | void show_usage(int argc, char * argv[]) {
  function main (line 83) | int main(int argc, char * argv[]) {

FILE: apps/wallpaper-picker.c
  type TT_Font (line 29) | struct TT_Font
  type TTKButton (line 39) | struct TTKButton
  type TTKButton (line 40) | struct TTKButton
  type TTKButton (line 41) | struct TTKButton
  type TTKButton (line 42) | struct TTKButton
  function redraw (line 47) | static void redraw(void) {
  function in_button (line 94) | int in_button(struct TTKButton * button, struct yutani_msg_window_mouse_...
  function setup_buttons (line 103) | void setup_buttons(void) {
  function resize_finish (line 132) | void resize_finish(int w, int h) {
  function set_hilight (line 142) | void set_hilight(struct TTKButton * button, int hilight) {
  function load_wallpaper (line 159) | void load_wallpaper(void) {
  function get_default_wallpaper (line 168) | void get_default_wallpaper(void) {
  function set_wallpaper (line 203) | void set_wallpaper(void) {
  function read_wallpapers (line 234) | void read_wallpapers(void) {
  function pick_wallpaper (line 260) | void pick_wallpaper(int dir) {
  function main (line 282) | int main(int argc, char * argv[]) {

FILE: apps/wc.c
  function main (line 16) | int main(int argc, char * argv[]) {

FILE: apps/weather-configurator.c
  type Value (line 16) | typedef struct JSON_Value Value;
  function main (line 18) | int main(int argc, char * argv[]) {

FILE: apps/weather-tool.c
  type Value (line 22) | typedef struct JSON_Value Value;
  function main (line 29) | int main(int argc, char * argv[]) {

FILE: apps/which.c
  function main (line 20) | int main(int argc, char * argv[]) {

FILE: apps/whoami.c
  function main (line 15) | int main(int argc, char ** argv) {

FILE: apps/yes.c
  function main (line 13) | int main(int argc, char * argv[]) {

FILE: apps/yutani-clipboard.c
  function show_usage (line 17) | void show_usage(int argc, char * argv[]) {
  function set_clipboard_from_file (line 36) | int set_clipboard_from_file(char * file) {
  function get_clipboard (line 57) | void get_clipboard(void) {
  function main (line 85) | int main(int argc, char * argv[]) {

FILE: apps/yutani-kbd.c
  function redraw (line 38) | void redraw(void) {
  function main (line 50) | int main (int argc, char ** argv) {

FILE: apps/yutani-query.c
  function show_usage (line 23) | void show_usage(int argc, char * argv[]) {
  function show_resolution (line 35) | int show_resolution(void) {
  function reload (line 44) | int reload(void) {
  function main (line 53) | int main(int argc, char * argv[]) {

FILE: apps/yutani-test.c
  function redraw (line 85) | void redraw(void) {
  function main (line 99) | int main (int argc, char ** argv) {

FILE: apps/yutani-tty-pipe.c
  function show_resolution (line 13) | int show_resolution(void) {
  function reload (line 22) | int reload(void) {
  type termios (line 31) | struct termios
  function set_unbuffered (line 33) | void set_unbuffered() {
  function main (line 41) | int main(int argc, char * argv[]) {

FILE: apps/zcat.c
  function main (line 4) | int main(int argc, char * argv[]) {

FILE: base/usr/include/arpa/inet.h
  type in_addr (line 21) | struct in_addr

FILE: base/usr/include/bits/dirent.h
  type dirent (line 9) | struct dirent {
  type DIR (line 15) | typedef struct DIR {
  type dirent (line 22) | struct dirent

FILE: base/usr/include/bits/timespec.h
  type timespec (line 3) | struct timespec {

FILE: base/usr/include/fcntl.h
  type flock (line 38) | struct flock {

FILE: base/usr/include/getopt.h
  function _Begin_C_Header (line 5) | _Begin_C_Header
  type option (line 17) | struct option

FILE: base/usr/include/kernel/arch/aarch64/dtb.h
  type fdt_header (line 4) | struct fdt_header {
  function swizzle (line 17) | static inline uint32_t swizzle(uint32_t from) {
  function swizzle64 (line 25) | static inline uint64_t swizzle64(uint64_t from) {
  function swizzle16 (line 37) | static inline uint16_t swizzle16(uint16_t from) {

FILE: base/usr/include/kernel/arch/aarch64/gic.h
  type irq_callback (line 5) | struct irq_callback {
  type irq_callback (line 15) | struct irq_callback

FILE: base/usr/include/kernel/arch/aarch64/regs.h
  type regs (line 4) | struct regs {

FILE: base/usr/include/kernel/arch/aarch64/rpi.h
  type rpitag (line 3) | struct rpitag {
  type rpitag (line 14) | struct rpitag

FILE: base/usr/include/kernel/arch/x86_64/acpi.h
  type rsdp_descriptor (line 5) | struct rsdp_descriptor {
  type rsdp_descriptor_20 (line 13) | struct rsdp_descriptor_20 {
  type acpi_sdt_header (line 22) | struct acpi_sdt_header {
  type rsdt (line 34) | struct rsdt {
  type madt (line 39) | struct madt {
  function acpi_checksum (line 46) | static inline int acpi_checksum(struct acpi_sdt_header * header) {

FILE: base/usr/include/kernel/arch/x86_64/irq.h
  type regs (line 5) | struct regs
  type regs (line 5) | struct regs
  type regs (line 6) | struct regs
  type regs (line 6) | struct regs
  type regs (line 7) | struct regs
  type regs (line 7) | struct regs
  type regs (line 8) | struct regs
  type regs (line 8) | struct regs
  type regs (line 9) | struct regs
  type regs (line 9) | struct regs
  type regs (line 10) | struct regs
  type regs (line 10) | struct regs
  type regs (line 11) | struct regs
  type regs (line 11) | struct regs
  type regs (line 12) | struct regs
  type regs (line 12) | struct regs
  type regs (line 13) | struct regs
  type regs (line 13) | struct regs
  type regs (line 14) | struct regs
  type regs (line 14) | struct regs
  type regs (line 15) | struct regs
  type regs (line 15) | struct regs
  type regs (line 16) | struct regs
  type regs (line 16) | struct regs
  type regs (line 17) | struct regs
  type regs (line 17) | struct regs
  type regs (line 18) | struct regs
  type regs (line 18) | struct regs
  type regs (line 19) | struct regs
  type regs (line 19) | struct regs
  type regs (line 20) | struct regs
  type regs (line 20) | struct regs
  type regs (line 21) | struct regs
  type regs (line 21) | struct regs
  type regs (line 22) | struct regs
  type regs (line 22) | struct regs
  type regs (line 23) | struct regs
  type regs (line 23) | struct regs
  type regs (line 24) | struct regs
  type regs (line 24) | struct regs
  type regs (line 25) | struct regs
  type regs (line 25) | struct regs
  type regs (line 26) | struct regs
  type regs (line 26) | struct regs
  type regs (line 27) | struct regs
  type regs (line 27) | struct regs
  type regs (line 28) | struct regs
  type regs (line 28) | struct regs
  type regs (line 29) | struct regs
  type regs (line 29) | struct regs
  type regs (line 30) | struct regs
  type regs (line 30) | struct regs
  type regs (line 31) | struct regs
  type regs (line 31) | struct regs
  type regs (line 32) | struct regs
  type regs (line 32) | struct regs
  type regs (line 33) | struct regs
  type regs (line 33) | struct regs
  type regs (line 34) | struct regs
  type regs (line 34) | struct regs
  type regs (line 35) | struct regs
  type regs (line 35) | struct regs
  type regs (line 36) | struct regs
  type regs (line 36) | struct regs
  type regs (line 37) | struct regs
  type regs (line 37) | struct regs
  type regs (line 38) | struct regs
  type regs (line 38) | struct regs
  type regs (line 39) | struct regs
  type regs (line 39) | struct regs
  type regs (line 40) | struct regs
  type regs (line 40) | struct regs
  type regs (line 41) | struct regs
  type regs (line 41) | struct regs
  type regs (line 42) | struct regs
  type regs (line 42) | struct regs
  type regs (line 43) | struct regs
  type regs (line 43) | struct regs
  type regs (line 44) | struct regs
  type regs (line 44) | struct regs
  type regs (line 45) | struct regs
  type regs (line 45) | struct regs
  type regs (line 46) | struct regs
  type regs (line 46) | struct regs
  type regs (line 47) | struct regs
  type regs (line 47) | struct regs
  type regs (line 48) | struct regs
  type regs (line 48) | struct regs
  type regs (line 49) | struct regs
  type regs (line 49) | struct regs
  type regs (line 50) | struct regs
  type regs (line 50) | struct regs
  type regs (line 51) | struct regs
  type regs (line 51) | struct regs
  type regs (line 52) | struct regs
  type regs (line 52) | struct regs
  type regs (line 53) | struct regs
  type regs (line 53) | struct regs
  type regs (line 54) | struct regs
  type regs (line 54) | struct regs
  type regs (line 55) | struct regs
  type regs (line 55) | struct regs
  type regs (line 56) | struct regs
  type regs (line 56) | struct regs
  type regs (line 57) | struct regs
  type regs (line 57) | struct regs
  type regs (line 59) | struct regs
  type regs (line 59) | struct regs
  type idt_entry_t (line 65) | typedef struct {
  type idt_pointer (line 77) | struct idt_pointer {
  type regs (line 85) | struct regs

FILE: base/usr/include/kernel/arch/x86_64/regs.h
  type regs (line 7) | struct regs {

FILE: base/usr/include/kernel/elf.h
  type Elf64_Addr (line 35) | typedef uint64_t Elf64_Addr;
  type Elf64_Off (line 36) | typedef uint64_t Elf64_Off;
  type Elf64_Half (line 37) | typedef uint16_t Elf64_Half;
  type Elf64_Word (line 38) | typedef uint32_t Elf64_Word;
  type Elf64_Sword (line 39) | typedef int32_t  Elf64_Sword;
  type Elf64_Xword (line 40) | typedef uint64_t Elf64_Xword;
  type Elf64_Sxword (line 41) | typedef int64_t  Elf64_Sxword;
  type Elf64_Header (line 92) | typedef struct Elf64_Header {
  type Elf64_Shdr (line 152) | typedef struct Elf64_Shdr {
  type Elf64_Sym (line 191) | typedef struct Elf64_Sym {
  type Elf64_Rel (line 208) | typedef struct Elf64_Rel {
  type Elf64_Rela (line 213) | typedef struct Elf64_Rela {
  type Elf64_Phdr (line 300) | typedef struct Elf64_Phdr {
  type Elf64_Dyn (line 349) | typedef struct Elf64_Dyn {

FILE: base/usr/include/kernel/hashmap.h
  type hashmap_entry_t (line 12) | typedef struct hashmap_entry {
  type hashmap_t (line 18) | typedef struct hashmap {

FILE: base/usr/include/kernel/list.h
  type node_t (line 9) | typedef struct node {
  type list_t (line 16) | typedef struct ListHeader {

FILE: base/usr/include/kernel/mod/shell.h
  type shell_command (line 11) | struct shell_command {
  type shell_command (line 17) | struct shell_command

FILE: base/usr/include/kernel/mod/snd.h
  type snd_mixer_enum_t (line 12) | typedef uint16_t snd_mixer_enum_t;
  type snd_knob_t (line 14) | typedef struct snd_knob {
  type snd_device_t (line 19) | typedef struct snd_device {

FILE: base/usr/include/kernel/mod/sound.h
  type snd_knob_list_t (line 12) | typedef struct snd_knob_list {
  type snd_knob_info_t (line 18) | typedef struct snd_knob_info {
  type snd_knob_value_t (line 24) | typedef struct snd_knob_value {

FILE: base/usr/include/kernel/module.h
  type Module (line 5) | struct Module {
  type LoadedModule (line 11) | struct LoadedModule {

FILE: base/usr/include/kernel/mouse.h
  type mouse_click_t (line 5) | typedef enum {
  type mouse_device_packet_t (line 14) | typedef struct {

FILE: base/usr/include/kernel/multiboot.h
  type multiboot (line 21) | struct multiboot
  type vbe_info_t (line 63) | typedef struct {
  type mboot_mod_t (line 88) | typedef struct {
  type mboot_memmap_t (line 95) | typedef struct {

FILE: base/usr/include/kernel/mutex.h
  type sched_mutex_t (line 12) | typedef struct {

FILE: base/usr/include/kernel/net/e1000.h
  type e1000_rx_desc (line 90) | struct e1000_rx_desc {
  type e1000_tx_desc (line 99) | struct e1000_tx_desc {

FILE: base/usr/include/kernel/net/eth.h
  type ethernet_packet (line 12) | struct ethernet_packet {
  type ethernet_packet (line 19) | struct ethernet_packet
  type EthernetDevice (line 21) | struct EthernetDevice {
  type EthernetDevice (line 38) | struct EthernetDevice
  type ArpCacheEntry (line 40) | struct ArpCacheEntry {
  type ArpCacheEntry (line 46) | struct ArpCacheEntry
  type EthernetDevice (line 47) | struct EthernetDevice

FILE: base/usr/include/kernel/net/ipv4.h
  type ipv4_packet (line 4) | struct ipv4_packet {
  type icmp_header (line 18) | struct icmp_header {
  type udp_packet (line 26) | struct udp_packet {
  type tcp_header (line 34) | struct tcp_header {
  type tcp_check_header (line 49) | struct tcp_check_header {

FILE: base/usr/include/kernel/net/netif.h
  type sock_t (line 15) | typedef struct SockData {
  type sockaddr (line 48) | struct sockaddr
  type sockaddr (line 49) | struct sockaddr
  type sockaddr (line 51) | struct sockaddr
  type msghdr (line 53) | struct msghdr
  type msghdr (line 54) | struct msghdr
  type sockaddr (line 56) | struct sockaddr
  type sockaddr (line 57) | struct sockaddr

FILE: base/usr/include/kernel/pci.h
  function pci_extract_bus (line 44) | static inline int pci_extract_bus(uint32_t device) {
  function pci_extract_slot (line 47) | static inline int pci_extract_slot(uint32_t device) {
  function pci_extract_func (line 50) | static inline int pci_extract_func(uint32_t device) {
  function pci_get_addr (line 54) | static inline uint32_t pci_get_addr(uint32_t device, int field) {
  function pci_box_device (line 58) | static inline uint32_t pci_box_device(int bus, int slot, int func) {

FILE: base/usr/include/kernel/pipe.h
  type pipe_device_t (line 8) | typedef struct _pipe_device {

FILE: base/usr/include/kernel/process.h
  type page_directory_t (line 27) | typedef struct {
  type kthread_context_t (line 33) | typedef struct {
  type thread_t (line 52) | typedef struct thread {
  type image_t (line 58) | typedef struct image {
  type fd_table_t (line 67) | typedef struct file_descriptors {
  type signal_config (line 77) | struct signal_config {
  type process_t (line 95) | typedef struct process {
  type sleeper_t (line 167) | typedef struct {
  type ProcessorLocal (line 174) | struct ProcessorLocal {
  type ProcessorLocal (line 224) | struct ProcessorLocal
  type ProcessorLocal (line 234) | struct ProcessorLocal
  type ProcessorLocal (line 236) | struct ProcessorLocal
  type regs (line 285) | struct regs
  type regs (line 287) | struct regs

FILE: base/usr/include/kernel/procfs.h
  type procfs_entry (line 7) | struct procfs_entry {
  type procfs_entry (line 13) | struct procfs_entry

FILE: base/usr/include/kernel/pty.h
  type pty_t (line 9) | typedef struct pty {
  type winsize (line 47) | struct winsize

FILE: base/usr/include/kernel/ringbuffer.h
  type ring_buffer_t (line 8) | typedef struct {

FILE: base/usr/include/kernel/shm.h
  type shm_node (line 10) | struct shm_node
  type shm_chunk_t (line 12) | typedef struct {
  type shm_node_t (line 20) | typedef struct shm_node {
  type shm_mapping_t (line 25) | typedef struct {

FILE: base/usr/include/kernel/signal.h
  type signal_t (line 15) | typedef struct {
  type regs (line 22) | struct regs
  type regs (line 23) | struct regs
  type regs (line 25) | struct regs

FILE: base/usr/include/kernel/spinlock.h
  type spin_lock_t (line 7) | typedef volatile struct {

FILE: base/usr/include/kernel/symboltable.h
  type kernel_symbol_t (line 6) | typedef struct {

FILE: base/usr/include/kernel/syscall.h
  type regs (line 22) | struct regs
  type regs (line 23) | struct regs
  type regs (line 24) | struct regs
  type regs (line 25) | struct regs
  type regs (line 26) | struct regs
  type regs (line 27) | struct regs
  type regs (line 29) | struct regs
  type regs (line 30) | struct regs
  type regs (line 32) | struct regs
  type regs (line 34) | struct regs

FILE: base/usr/include/kernel/tmpfs.h
  type tmpfs_file (line 9) | struct tmpfs_file {
  type tmpfs_dir (line 27) | struct tmpfs_dir
  type tmpfs_dir (line 29) | struct tmpfs_dir {

FILE: base/usr/include/kernel/tree.h
  type tree_node_t (line 5) | typedef struct tree_node {
  type tree_t (line 11) | typedef struct {

FILE: base/usr/include/kernel/vfs.h
  type fs_node (line 34) | struct fs_node
  type fs_node (line 36) | struct fs_node
  type fs_node (line 37) | struct fs_node
  type fs_node (line 38) | struct fs_node
  type fs_node (line 39) | struct fs_node
  type dirent (line 40) | struct dirent
  type fs_node (line 40) | struct fs_node
  type fs_node (line 41) | struct fs_node
  type fs_node (line 41) | struct fs_node
  type fs_node (line 42) | struct fs_node
  type fs_node (line 43) | struct fs_node
  type fs_node (line 44) | struct fs_node
  type fs_node (line 45) | struct fs_node
  type fs_node (line 46) | struct fs_node
  type fs_node (line 47) | struct fs_node
  type fs_node (line 48) | struct fs_node
  type fs_node (line 49) | struct fs_node
  type fs_node (line 50) | struct fs_node
  type fs_node (line 51) | struct fs_node
  type fs_node (line 52) | struct fs_node
  type fs_node (line 53) | struct fs_node
  type fs_node (line 54) | struct fs_node
  type fs_node (line 54) | struct fs_node
  type fs_node (line 54) | struct fs_node
  type fs_node_t (line 56) | typedef struct fs_node {
  type vfs_entry (line 99) | struct vfs_entry {
  type dirent (line 114) | struct dirent
  type fs_node_t (line 133) | typedef fs_node_t * (*vfs_mount_callback)(const char * arg, const char *...

FILE: base/usr/include/kernel/video.h
  type vid_size (line 15) | struct vid_size {

FILE: base/usr/include/locale.h
  type lconv (line 15) | struct lconv {
  type lconv (line 36) | struct lconv

FILE: base/usr/include/net/if.h
  type netif_counters_t (line 35) | typedef struct {

FILE: base/usr/include/netdb.h
  type sockaddr (line 9) | struct sockaddr
  type addrinfo (line 14) | struct addrinfo
  type addrinfo (line 15) | struct addrinfo
  type addrinfo (line 17) | struct addrinfo
  type hostent (line 19) | struct hostent {
  type hostent (line 27) | struct hostent

FILE: base/usr/include/netinet/in.h
  type in_port_t (line 8) | typedef uint16_t in_port_t;
  type in_addr (line 10) | struct in_addr {
  type sockaddr_in (line 14) | struct sockaddr_in {

FILE: base/usr/include/poll.h
  type nfds_t (line 15) | typedef unsigned int nfds_t;
  type pollfd (line 17) | struct pollfd {
  type pollfd (line 23) | struct pollfd

FILE: base/usr/include/pthread.h
  type __pthread (line 8) | struct __pthread
  type pthread_attr_t (line 9) | typedef unsigned int pthread_attr_t;
  type pthread_rwlock_t (line 11) | typedef struct {
  type pthread_mutex_t (line 27) | typedef int volatile pthread_mutex_t;
  type pthread_mutexattr_t (line 28) | typedef int pthread_mutexattr_t;

FILE: base/usr/include/pty.h
  type termios (line 7) | struct termios
  type winsize (line 7) | struct winsize

FILE: base/usr/include/pwd.h
  function _Begin_C_Header (line 7) | _Begin_C_Header
  type passwd (line 20) | struct passwd
  type passwd (line 22) | struct passwd
  type passwd (line 25) | struct passwd
  type passwd (line 26) | struct passwd

FILE: base/usr/include/signal.h
  type sig_atomic_t (line 15) | typedef int sig_atomic_t;
  type sigaction (line 19) | struct sigaction
  type sigaction (line 19) | struct sigaction

FILE: base/usr/include/stdint.h
  type int_least8_t (line 47) | typedef signed char int_least8_t;
  type uint_least8_t (line 48) | typedef unsigned char uint_least8_t;
  type int_least16_t (line 67) | typedef int16_t   	int_least16_t;
  type uint_least16_t (line 68) | typedef uint16_t 	uint_least16_t;
  type int_least8_t (line 72) | typedef int16_t	   	int_least8_t;
  type uint_least8_t (line 73) | typedef uint16_t  	uint_least8_t;
  type int_least32_t (line 97) | typedef int32_t   	int_least32_t;
  type uint_least32_t (line 98) | typedef uint32_t 	uint_least32_t;
  type int_least8_t (line 102) | typedef int32_t	   	int_least8_t;
  type uint_least8_t (line 103) | typedef uint32_t  	uint_least8_t;
  type int_least16_t (line 108) | typedef int32_t	   	int_least16_t;
  type uint_least16_t (line 109) | typedef uint32_t  	uint_least16_t;
  type int_least64_t (line 129) | typedef int64_t   	int_least64_t;
  type uint_least64_t (line 130) | typedef uint64_t 	uint_least64_t;
  type int_least8_t (line 134) | typedef int64_t	   	int_least8_t;
  type uint_least8_t (line 135) | typedef uint64_t  	uint_least8_t;
  type int_least16_t (line 140) | typedef int64_t	   	int_least16_t;
  type uint_least16_t (line 141) | typedef uint64_t  	uint_least16_t;
  type int_least32_t (line 146) | typedef int64_t	   	int_least32_t;
  type uint_least32_t (line 147) | typedef uint64_t  	uint_least32_t;
  type int_fast8_t (line 159) | typedef signed int int_fast8_t;
  type uint_fast8_t (line 160) | typedef unsigned int uint_fast8_t;
  type int_fast16_t (line 165) | typedef signed int int_fast16_t;
  type uint_fast16_t (line 166) | typedef unsigned int uint_fast16_t;
  type int_fast32_t (line 171) | typedef signed int int_fast32_t;
  type uint_fast32_t (line 172) | typedef unsigned int uint_fast32_t;
  type int_fast64_t (line 177) | typedef signed int int_fast64_t;
  type uint_fast64_t (line 178) | typedef unsigned int uint_fast64_t;
  type int_least8_t (line 189) | typedef int_least8_t int_fast8_t;
  type uint_least8_t (line 190) | typedef uint_least8_t uint_fast8_t;
  type int_least16_t (line 197) | typedef int_least16_t int_fast16_t;
  type uint_least16_t (line 198) | typedef uint_least16_t uint_fast16_t;
  type int_least32_t (line 205) | typedef int_least32_t int_fast32_t;
  type uint_least32_t (line 206) | typedef uint_least32_t uint_fast32_t;
  type int_least64_t (line 213) | typedef int_least64_t int_fast64_t;
  type uint_least64_t (line 214) | typedef uint_least64_t uint_fast64_t;
  type __INTMAX_TYPE__ (line 222) | typedef __INTMAX_TYPE__ intmax_t;
  type intmax_t (line 224) | typedef signed long long intmax_t;
  type intmax_t (line 226) | typedef signed long intmax_t;
  type __UINTMAX_TYPE__ (line 231) | typedef __UINTMAX_TYPE__ uintmax_t;
  type uintmax_t (line 233) | typedef unsigned long long uintmax_t;
  type uintmax_t (line 235) | typedef unsigned long uintmax_t;

FILE: base/usr/include/stdio.h
  type _FILE (line 10) | struct _FILE
  type fpos_t (line 92) | typedef long fpos_t;

FILE: base/usr/include/stdlib.h
  type div_t (line 64) | typedef struct { int quot; int rem; } div_t;
  type ldiv_t (line 65) | typedef struct { long int quot; long int rem; } ldiv_t;

FILE: base/usr/include/sys/ptrace.h
  type __ptrace_event (line 21) | enum __ptrace_event {
  type __ptrace_request (line 28) | enum __ptrace_request

FILE: base/usr/include/sys/signal.h
  type sigevent (line 35) | struct sigevent {
  type siginfo_t (line 41) | typedef struct {
  type sigset_t (line 47) | typedef unsigned long sigset_t;
  type sigaction (line 50) | struct sigaction {

FILE: base/usr/include/sys/socket.h
  type socklen_t (line 30) | typedef size_t socklen_t;
  type sockaddr (line 32) | struct sockaddr {
  type addrinfo (line 37) | struct addrinfo {
  type iovec (line 48) | struct iovec {                    /* Scatter/gather array items */
  type msghdr (line 53) | struct msghdr {
  type sockaddr_storage (line 63) | struct sockaddr_storage {
  type cmsghdr (line 68) | struct cmsghdr {
  type sockaddr (line 79) | struct sockaddr
  type msghdr (line 80) | struct msghdr
  type sockaddr (line 83) | struct sockaddr
  type msghdr (line 84) | struct msghdr
  type sockaddr (line 88) | struct sockaddr
  type sockaddr (line 89) | struct sockaddr
  type sockaddr (line 90) | struct sockaddr
  type sockaddr (line 92) | struct sockaddr
  type sockaddr (line 93) | struct sockaddr
  type sockaddr (line 97) | struct sockaddr

FILE: base/usr/include/sys/stat.h
  function _Begin_C_Header (line 8) | _Begin_C_Header
  type stat (line 78) | struct stat
  type stat (line 79) | struct stat
  type stat (line 80) | struct stat
  type stat (line 81) | struct stat
  type stat (line 82) | struct stat
  type stat (line 83) | struct stat

FILE: base/usr/include/sys/termios.h
  function _Begin_C_Header (line 7) | _Begin_C_Header
  type tcflag_t (line 17) | typedef unsigned int tcflag_t;
  type speed_t (line 18) | typedef unsigned int speed_t;
  type cc_t (line 19) | typedef unsigned char cc_t;
  type termios (line 149) | struct termios {
  type termios (line 191) | struct termios
  type termios (line 192) | struct termios
  type termios (line 193) | struct termios
  type termios (line 194) | struct termios
  type termios (line 198) | struct termios
  type termios (line 201) | struct termios

FILE: base/usr/include/sys/time.h
  function _Begin_C_Header (line 6) | _Begin_C_Header
  type timezone (line 13) | struct timezone {
  type timeval (line 18) | struct timeval
  type timeval (line 19) | struct timeval

FILE: base/usr/include/sys/times.h
  function _Begin_C_Header (line 6) | _Begin_C_Header
  type tms (line 15) | struct tms

FILE: base/usr/include/sys/types.h
  type uid_t (line 9) | typedef int uid_t;
  type dev_t (line 10) | typedef unsigned long dev_t;
  type ino_t (line 11) | typedef unsigned long ino_t;
  type mode_t (line 12) | typedef int mode_t;
  type caddr_t (line 13) | typedef int caddr_t;
  type nlink_t (line 15) | typedef unsigned short nlink_t;
  type blksize_t (line 17) | typedef unsigned long blksize_t;
  type blkcnt_t (line 18) | typedef unsigned long blkcnt_t;
  type off_t (line 20) | typedef long off_t;
  type time_t (line 21) | typedef long time_t;
  type clock_t (line 22) | typedef long clock_t;
  type useconds_t (line 29) | typedef unsigned long useconds_t;
  type suseconds_t (line 30) | typedef long suseconds_t;
  type pid_t (line 31) | typedef int pid_t;
  type fd_mask (line 34) | typedef unsigned int fd_mask;
  type fd_set (line 35) | typedef struct _fd_set {

FILE: base/usr/include/sys/uregs.h
  type URegs (line 64) | struct URegs {

FILE: base/usr/include/sys/utsname.h
  type utsname (line 8) | struct utsname {
  type utsname (line 19) | struct utsname

FILE: base/usr/include/time.h
  function _Begin_C_Header (line 7) | _Begin_C_Header
  type tm (line 24) | struct tm
  type tm (line 25) | struct tm
  type tm (line 27) | struct tm
  type tm (line 27) | struct tm
  type tm (line 28) | struct tm
  type tm (line 28) | struct tm
  type tm (line 30) | struct tm
  type tm (line 33) | struct tm
  type tm (line 35) | struct tm
  type clockid_t (line 43) | typedef int clockid_t;
  type timespec (line 48) | struct timespec
  type timespec (line 49) | struct timespec

FILE: base/usr/include/toaru/button.h
  type TTKButton (line 11) | struct TTKButton {
  type TTKButton (line 20) | struct TTKButton

FILE: base/usr/include/toaru/confreader.h
  function _Begin_C_Header (line 21) | _Begin_C_Header

FILE: base/usr/include/toaru/decodeutf8.h
  function decode (line 24) | static inline uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t...

FILE: base/usr/include/toaru/decorations.h
  type decor_bounds (line 32) | struct decor_bounds {
  type decor_bounds (line 48) | struct decor_bounds

FILE: base/usr/include/toaru/graphics.h
  type sprite_t (line 27) | typedef struct sprite {
  type gfx_context_t (line 36) | typedef struct context {
  type gfx_point (line 107) | struct gfx_point {
  type gfx_point (line 112) | struct gfx_point
  type gfx_point (line 112) | struct gfx_point
  type gfx_point (line 113) | struct gfx_point
  type gfx_point (line 113) | struct gfx_point
  type gfx_point (line 114) | struct gfx_point
  type gfx_point (line 114) | struct gfx_point
  type gfx_point (line 115) | struct gfx_point
  type gfx_point (line 115) | struct gfx_point
  type gfx_point (line 115) | struct gfx_point
  type gfx_point (line 116) | struct gfx_point
  type gfx_point (line 116) | struct gfx_point
  type gfx_point (line 116) | struct gfx_point
  type gfx_point (line 117) | struct gfx_point
  type gfx_point (line 117) | struct gfx_point
  type gfx_point (line 117) | struct gfx_point
  type gfx_point (line 118) | struct gfx_point
  type gfx_point (line 118) | struct gfx_point
  type gradient_definition (line 121) | struct gradient_definition {

FILE: base/usr/include/toaru/hashmap.h
  type hashmap_entry_t (line 22) | typedef struct hashmap_entry {
  type hashmap_t (line 28) | typedef struct hashmap {

FILE: base/usr/include/toaru/inflate.h
  type inflate_context (line 19) | struct inflate_context {
  type inflate_context (line 37) | struct inflate_context
  type inflate_context (line 38) | struct inflate_context

FILE: base/usr/include/toaru/json.h
  type JSON_Value (line 16) | struct JSON_Value {
  type JSON_Value (line 36) | struct JSON_Value
  type JSON_Value (line 43) | struct JSON_Value
  type JSON_Value (line 51) | struct JSON_Value

FILE: base/usr/include/toaru/kbd.h
  type kbd_key_t (line 107) | typedef unsigned int  kbd_key_t;
  type kbd_mod_t (line 108) | typedef unsigned int  kbd_mod_t;
  type kbd_act_t (line 109) | typedef unsigned char kbd_act_t;
  type key_event_t (line 111) | typedef struct {
  type key_event_state_t (line 119) | typedef struct {

FILE: base/usr/include/toaru/list.h
  type node (line 15) | struct node {
  type list_t (line 22) | typedef struct {

FILE: base/usr/include/toaru/markup.h
  function _Begin_C_Header (line 6) | _Begin_C_Header
  type markup_state (line 13) | struct markup_state
  type markup_state (line 14) | struct markup_state
  type markup_tag (line 14) | struct markup_tag
  type markup_state (line 15) | struct markup_state
  type markup_state (line 16) | struct markup_state
  type markup_state (line 18) | struct markup_state
  type markup_tag (line 19) | struct markup_tag
  type markup_state (line 20) | struct markup_state
  type markup_state (line 21) | struct markup_state

FILE: base/usr/include/toaru/markup_text.h
  type MarkupState (line 11) | struct MarkupState
  type MarkupState (line 12) | struct MarkupState
  type MarkupState (line 13) | struct MarkupState
  type MarkupState (line 14) | struct MarkupState
  type MarkupState (line 15) | struct MarkupState
  type MarkupState (line 16) | struct MarkupState

FILE: base/usr/include/toaru/menu.h
  type MenuList (line 19) | struct MenuList
  type MenuEntry (line 20) | struct MenuEntry
  type MenuEntryVTable (line 22) | struct MenuEntryVTable {
  type MenuEntry (line 30) | struct MenuEntry {
  type MenuEntry_Normal (line 45) | struct MenuEntry_Normal {
  type MenuEntry_Toggle (line 53) | struct MenuEntry_Toggle {
  type MenuEntry_Submenu (line 58) | struct MenuEntry_Submenu {
  type MenuEntry_Separator (line 63) | struct MenuEntry_Separator {
  type MenuList (line 67) | struct MenuList {
  type MenuSet (line 81) | struct MenuSet {
  type MenuEntry (line 85) | struct MenuEntry
  type MenuEntry (line 85) | struct MenuEntry
  type MenuEntry (line 86) | struct MenuEntry
  type MenuEntry (line 86) | struct MenuEntry
  type MenuEntry (line 87) | struct MenuEntry
  type MenuEntry (line 88) | struct MenuEntry
  type MenuList (line 89) | struct MenuList
  type MenuSet (line 90) | struct MenuSet
  type MenuEntry (line 90) | struct MenuEntry
  type MenuList (line 92) | struct MenuList
  type MenuEntry (line 92) | struct MenuEntry
  type MenuList (line 93) | struct MenuList
  type MenuList (line 94) | struct MenuList
  type MenuList (line 96) | struct MenuList
  type MenuSet (line 96) | struct MenuSet
  type MenuList (line 97) | struct MenuList
  type MenuSet (line 97) | struct MenuSet
  type MenuList (line 98) | struct MenuList
  type MenuEntry (line 100) | struct MenuEntry
  type MenuList (line 101) | struct MenuList
  type MenuSet (line 102) | struct MenuSet
  type MenuList (line 105) | struct MenuList
  type MenuSet (line 106) | struct MenuSet
  type MenuSet (line 107) | struct MenuSet
  type MenuList (line 107) | struct MenuList
  type MenuEntry (line 108) | struct MenuEntry
  type MenuList (line 109) | struct MenuList
  type MenuEntry (line 110) | struct MenuEntry
  type MenuEntry (line 111) | struct MenuEntry
  type MenuEntry (line 112) | struct MenuEntry
  type menu_bar_entries (line 122) | struct menu_bar_entries {
  type menu_bar (line 127) | struct menu_bar {
  type menu_bar (line 148) | struct menu_bar
  type menu_bar (line 149) | struct menu_bar
  type yutani_msg_window_mouse_event (line 149) | struct yutani_msg_window_mouse_event
  type menu_bar (line 150) | struct menu_bar
  type menu_bar_entries (line 150) | struct menu_bar_entries

FILE: base/usr/include/toaru/mouse.h
  type mouse_device_packet_t (line 16) | typedef struct {

FILE: base/usr/include/toaru/panel.h
  function _Begin_C_Header (line 19) | _Begin_C_Header
  type PanelWidget (line 40) | struct PanelWidget {
  type PanelWidget (line 59) | struct PanelWidget
  type MenuEntry (line 61) | struct MenuEntry
  type window_ad (line 63) | struct window_ad {
  type window_ad (line 75) | struct window_ad
  type PanelWidget (line 78) | struct PanelWidget
  type MenuList (line 78) | struct MenuList
  type MenuList (line 79) | struct MenuList
  type PanelWidget (line 80) | struct PanelWidget

FILE: base/usr/include/toaru/pex.h
  type pex_packet (line 9) | struct pex_packet {
  type pex_header_t (line 17) | typedef struct pex_header {

FILE: base/usr/include/toaru/rline.h
  type rline_callback (line 3) | struct rline_callback
  type rline_context_t (line 5) | typedef struct {
  type rline_callbacks_t (line 19) | typedef struct rline_callback {
  type rline_style_t (line 30) | typedef enum {

FILE: base/usr/include/toaru/spinlock.h
  function spin_lock (line 4) | static void spin_lock(int volatile * lock) {
  function spin_unlock (line 10) | static void spin_unlock(int volatile * lock) {

FILE: base/usr/include/toaru/termemu.h
  type term_cell_t (line 11) | typedef struct {
  type term_callbacks_t (line 18) | typedef struct {
  type term_state_t (line 39) | typedef struct {

FILE: base/usr/include/toaru/text.h
  type TT_Font (line 11) | struct TT_Font
  type TT_Font (line 12) | struct TT_Font
  type TT_Font (line 15) | struct TT_Font
  type TT_Font (line 16) | struct TT_Font
  type TT_Font (line 19) | struct TT_Font
  type TT_Font (line 20) | struct TT_Font
  type TT_Font (line 21) | struct TT_Font
  type TT_Font (line 22) | struct TT_Font
  type TT_Font (line 23) | struct TT_Font
  type TT_Font (line 26) | struct TT_Font
  type TT_Font (line 27) | struct TT_Font
  type TT_Font (line 28) | struct TT_Font
  type TT_Font (line 29) | struct TT_Font
  type TT_FontMetrics (line 31) | struct TT_FontMetrics {
  type TT_Font (line 37) | struct TT_Font
  type TT_FontMetrics (line 37) | struct TT_FontMetrics
  type TT_Contour (line 40) | struct TT_Contour
  type TT_Shape (line 41) | struct TT_Shape
  type TT_Contour (line 41) | struct TT_Contour
  type TT_Contour (line 42) | struct TT_Contour
  type TT_Contour (line 42) | struct TT_Contour
  type TT_Shape (line 43) | struct TT_Shape
  type TT_Contour (line 43) | struct TT_Contour
  type TT_Contour (line 44) | struct TT_Contour
  type TT_Contour (line 44) | struct TT_Contour
  type TT_Contour (line 45) | struct TT_Contour
  type TT_Contour (line 45) | struct TT_Contour
  type TT_Shape (line 46) | struct TT_Shape
  type TT_Contour (line 47) | struct TT_Contour
  type TT_Contour (line 50) | struct TT_Contour
  type TT_Contour (line 50) | struct TT_Contour
  type TT_Font (line 50) | struct TT_Font
  type TT_Contour (line 51) | struct TT_Contour
  type TT_Font (line 51) | struct TT_Font
  type TT_Contour (line 52) | struct TT_Contour
  type TT_Contour (line 52) | struct TT_Contour
  type TT_Font (line 52) | struct TT_Font
  type TT_Shape (line 55) | struct TT_Shape
  type TT_Shape (line 56) | struct TT_Shape
  type TT_Font (line 59) | struct TT_Font

FILE: base/usr/include/toaru/tree.h
  type tree_node (line 8) | struct tree_node {
  type tree_t (line 14) | typedef struct {

FILE: base/usr/include/toaru/yutani-server.h
  type yutani_effect (line 41) | typedef enum {
  type yutani_server_window_t (line 111) | typedef struct YutaniServerWindow {
  type yutani_globals_t (line 182) | typedef struct YutaniGlobals {
  type key_bind (line 336) | struct key_bind {

FILE: base/usr/include/toaru/yutani.h
  type yutani_t (line 31) | typedef struct yutani_context {
  type yutani_window_t (line 48) | typedef struct yutani_window {
  type yutani_msg_t (line 87) | typedef struct yutani_message {
  type yutani_msg_welcome (line 94) | struct yutani_msg_welcome {
  type yutani_msg_flip (line 99) | struct yutani_msg_flip {
  type yutani_msg_window_close (line 103) | struct yutani_msg_window_close {
  type yutani_msg_window_new (line 107) | struct yutani_msg_window_new {
  type yutani_msg_window_new_flags (line 112) | struct yutani_msg_window_new_flags {
  type yutani_msg_window_init (line 119) | struct yutani_msg_window_init {
  type yutani_msg_window_move (line 126) | struct yutani_msg_window_move {
  type yutani_msg_window_move_relative (line 132) | struct yutani_msg_window_move_relative {
  type yutani_msg_key_event (line 139) | struct yutani_msg_key_event {
  type yutani_msg_window_stack (line 145) | struct yutani_msg_window_stack {
  type yutani_msg_window_focus_change (line 150) | struct yutani_msg_window_focus_change {
  type yutani_msg_window_mouse_event (line 155) | struct yutani_msg_window_mouse_event {
  type yutani_msg_mouse_event (line 166) | struct yutani_msg_mouse_event {
  type yutani_msg_flip_region (line 172) | struct yutani_msg_flip_region {
  type yutani_msg_window_resize (line 180) | struct yutani_msg_window_resize {
  type yutani_msg_window_advertise (line 188) | struct yutani_msg_window_advertise {
  type yutani_msg_window_focus (line 199) | struct yutani_msg_window_focus {
  type yutani_msg_key_bind (line 203) | struct yutani_msg_key_bind {
  type yutani_msg_window_drag_start (line 209) | struct yutani_msg_window_drag_start {
  type yutani_msg_window_update_shape (line 213) | struct yutani_msg_window_update_shape {
  type yutani_msg_window_warp_mouse (line 218) | struct yutani_msg_window_warp_mouse {
  type yutani_msg_window_show_mouse (line 224) | struct yutani_msg_window_show_mouse {
  type yutani_scale_direction_t (line 229) | typedef enum {
  type yutani_msg_window_resize_start (line 245) | struct yutani_msg_window_resize_start {
  type yutani_msg_special_request (line 250) | struct yutani_msg_special_request {
  type yutani_msg_clipboard (line 255) | struct yutani_msg_clipboard {
  type yutani_msg_window_panel_size (line 260) | struct yutani_msg_window_panel_size {
  type yutani_msg_window_set_parent (line 268) | struct yutani_msg_window_set_parent {
  type yutani_damage_rect_t (line 527) | typedef struct {

FILE: base/usr/include/utime.h
  function _Begin_C_Header (line 6) | _Begin_C_Header
  type utimbuf (line 13) | struct utimbuf

FILE: base/usr/include/wchar.h
  type wint_t (line 25) | typedef unsigned int wint_t;

FILE: boot/config.c
  type bootmode (line 53) | struct bootmode
  function kmain (line 65) | int kmain() {

FILE: boot/editor.c
  function draw_text (line 24) | static void draw_text(int cursor, int len) {
  function boot_editor (line 44) | int boot_editor(void) {

FILE: boot/elf.h
  type Elf32_Word (line 8) | typedef uint32_t Elf32_Word;
  type Elf32_Addr (line 9) | typedef uint32_t Elf32_Addr;
  type Elf32_Off (line 10) | typedef uint32_t Elf32_Off;
  type Elf32_Sword (line 11) | typedef uint32_t Elf32_Sword;
  type Elf32_Half (line 12) | typedef uint16_t Elf32_Half;
  type Elf32_Header (line 17) | typedef struct {
  type Elf32_Phdr (line 56) | typedef struct {
  type Elf32_Shdr (line 80) | typedef struct {
  type Elf32_auxv (line 93) | typedef struct {
  type Elf32_Sym (line 98) | typedef struct {
  type Elf32_Rel (line 107) | typedef struct {
  type Elf32_Dyn (line 112) | typedef struct {

FILE: boot/iso9660.h
  type iso_9660_datetime_t (line 5) | typedef struct {
  type iso_9660_rec_date_t (line 16) | typedef struct {
  type iso_9660_directory_entry_t (line 26) | typedef struct {
  type iso_9660_volume_descriptor_t (line 49) | typedef struct {

FILE: boot/kbd.c
  function read_scancode (line 34) | int read_scancode(int timeout) {
  function read_key (line 78) | int read_key(int * c) {
  function read_cmos_seconds (line 103) | int read_cmos_seconds(void) {
  function read_key (line 128) | int read_key(int * c) {
  function kbd_status (line 145) | int kbd_status(void) {
  function read_scancode (line 150) | int read_scancode(int timeout) {

FILE: boot/menu.c
  type option (line 20) | struct option
  function toggle (line 26) | void toggle(int ndx, int value, char *str) {
  function show_menu (line 45) | void show_menu(void) {

FILE: boot/multiboot.c
  type multiboot (line 31) | struct multiboot
  function read_tsc (line 64) | static inline uint64_t read_tsc(void) {
  function load_aout (line 70) | static int load_aout(uint32_t * hdr) {
  function load_elf32 (line 91) | static int load_elf32(Elf32_Header * header) {
  function load_kernel (line 123) | static int load_kernel(void) {
  function relocate_ramdisk (line 141) | static void relocate_ramdisk(mboot_mod_t * mboot_mods) {
  function finish_boot (line 170) | static void finish_boot(void) {
  function boot (line 288) | void boot(void) {
  type mmap_entry (line 440) | struct mmap_entry {
  function finish_boot (line 450) | static void finish_boot(void) {
  function spin (line 514) | static void spin(void) {
  function clear_spin (line 520) | static void clear_spin(void) {
  function boot (line 534) | void boot(void) {

FILE: boot/multiboot.h
  type multiboot (line 19) | struct multiboot
  type vbe_info_t (line 53) | typedef struct {
  type mboot_mod_t (line 78) | typedef struct {
  type mboot_memmap_t (line 85) | typedef struct {
  type multiboot (line 92) | struct multiboot
  type multiboot (line 92) | struct multiboot
  type multiboot (line 93) | struct multiboot
  type multiboot (line 95) | struct multiboot

FILE: boot/options.h
  type option (line 3) | struct option {
  type option (line 10) | struct option
  type bootmode (line 21) | struct bootmode {
  type bootmode (line 45) | struct bootmode

FILE: boot/platform.c
  function EFI_STATUS (line 22) | EFI_STATUS
  function text_reset (line 69) | void text_reset(void) {
  function bios_text_mode (line 85) | int bios_text_mode(void) {
  function bios_set_video (line 97) | void bios_set_video(int mode) {
  function bios_video_mode (line 104) | int bios_video_mode(void) {
  function bios_toggle_mode (line 144) | void bios_toggle_mode(void) {
  function bios_main (line 152) | int bios_main(void) {
  function bios_call (line 170) | int bios_call(char * into, uint32_t sector) {
  function navigate (line 183) | int navigate(char * name) {

FILE: boot/qemu.c
  type fw_cfg_file (line 22) | struct fw_cfg_file {
  function swap_bytes (line 30) | void swap_bytes(void * in, int count) {
  function detect_qemu (line 41) | int detect_qemu(void) {

FILE: boot/text.c
  function init_graphics (line 47) | int init_graphics() {
  function set_point (line 77) | static void set_point(int x, int y, uint32_t color) {
  function clear_ (line 80) | void clear_() {
  function placech (line 86) | static void placech(unsigned char c, int x, int y, int attr) {
  function init_graphics (line 99) | void init_graphics(void) {
  function set_point (line 109) | static void set_point(int x, int y, uint32_t color) {
  function placech_vga (line 121) | static void placech_vga(unsigned char c, int x, int y, int attr) {
  function placech (line 128) | static void placech(unsigned char c, int x, int y, int attr) {
  function clear_ (line 132) | void clear_() {
  function write_char (line 173) | static void write_char(int x, int y, int val, int attr) {
  function print_ (line 196) | void print_(char * str) {
  function move_cursor (line 222) | void move_cursor(int _x, int _y) {
  function set_attr (line 227) | void set_attr(int _attr) {
  function print_banner (line 231) | void print_banner(char * str) {
  function print_hex_ (line 254) | void print_hex_(unsigned int value) {
  function print_int_ (line 262) | void print_int_(unsigned int value) {
  function draw_square (line 287) | static void draw_square(int x, int y, int stage) {
  function draw_logo (line 305) | void draw_logo(int stage) {

FILE: boot/util.c
  function strcmp (line 13) | int strcmp(const char * l, const char * r) {
  function strlen (line 28) | unsigned long strlen(const char *s) {

FILE: boot/util.h
  function inports (line 3) | static inline unsigned short inports(unsigned short _port) {
  function outports (line 9) | static inline void outports(unsigned short _port, unsigned short _data) {
  function inportl (line 13) | static inline unsigned int inportl(unsigned short _port) {
  function outportl (line 19) | static inline void outportl(unsigned short _port, unsigned int _data) {
  function inportb (line 23) | static inline unsigned char inportb(unsigned short _port) {
  function outportb (line 29) | static inline void outportb(unsigned short _port, unsigned char _data) {
  function inportsm (line 33) | static inline void inportsm(unsigned short port, unsigned char * data, u...

FILE: boot/video.c
  function mode_selector (line 28) | void mode_selector(int sel, int ndx, char *str) {
  function video_menu (line 73) | int video_menu(void) {
  function platform_list_modes (line 134) | int platform_list_modes(int sel, int select_this_mode) {
  function platform_count_modes (line 164) | int platform_count_modes(int * current) {
  type ColorFormat (line 185) | struct ColorFormat {
  type VbeMode (line 190) | struct VbeMode {
  type VbeMode (line 219) | struct VbeMode
  type VbeMode (line 220) | struct VbeMode
  function qualified (line 222) | static int qualified(void) {
  function platform_list_modes (line 231) | int platform_list_modes(int sel, int select_this_mode) {
  function platform_count_modes (line 263) | int platform_count_modes(int * current) {

FILE: kernel/arch/aarch64/arch.c
  function arch_enter_user (line 34) | void arch_enter_user(uintptr_t entrypoint, int argc, char * argv[], char...
  function _kill_it (line 56) | static void _kill_it(uintptr_t addr, const char * action, const char * d...
  function arch_return_from_signal_handler (line 76) | int arch_return_from_signal_handler(struct regs *r) {
  function arch_enter_signal_handler (line 122) | void arch_enter_signal_handler(uintptr_t entrypoint, int signum, struct ...
  function arch_restore_floating (line 177) | void arch_restore_floating(process_t * proc) {
  function arch_save_floating (line 222) | void arch_save_floating(process_t * proc) {
  function arch_fatal_prepare (line 268) | void arch_fatal_prepare(void) {
  function arch_fatal (line 278) | void arch_fatal(void) {
  function arch_wakeup_others (line 285) | void arch_wakeup_others(void) {
  function arch_reboot (line 303) | long arch_reboot(void) {
  function aarch64_regs (line 327) | void aarch64_regs(struct regs *r) {
  function aarch64_context (line 348) | void aarch64_context(process_t * proc) {
  function arch_syscall_return (line 361) | void arch_syscall_return(struct regs * r, long retval) { r->x0 = retval; }
  function arch_syscall_number (line 362) | long arch_syscall_number(struct regs * r) { return r->x0; }
  function arch_syscall_arg0 (line 363) | long arch_syscall_arg0(struct regs * r)   { return r->x1; }
  function arch_syscall_arg1 (line 364) | long arch_syscall_arg1(struct regs * r)   { return r->x2; }
  function arch_syscall_arg2 (line 365) | long arch_syscall_arg2(struct regs * r)   { return r->x3; }
  function arch_syscall_arg3 (line 366) | long arch_syscall_arg3(struct regs * r)   { return r->x4; }
  function arch_syscall_arg4 (line 367) | long arch_syscall_arg4(struct regs * r)   { return r->x5; }
  function arch_stack_pointer (line 368) | long arch_stack_pointer(struct regs * r)  { return r->user_sp; }
  function arch_user_ip (line 369) | long arch_user_ip(struct regs * r)        { return r->x30; /* TODO this ...
  function inports (line 373) | unsigned short inports(unsigned short _port) { return 0; }
  function inportl (line 374) | unsigned int inportl(unsigned short _port)   { return 0; }
  function inportb (line 375) | unsigned char inportb(unsigned short _port)  { return 0; }
  function inportsm (line 376) | void inportsm(unsigned short port, unsigned char * data, unsigned long s...
  function outports (line 379) | void outports(unsigned short _port, unsigned short _data) {
  function outportl (line 382) | void outportl(unsigned short _port, unsigned int _data) {
  function outportb (line 385) | void outportb(unsigned short _port, unsigned char _data) {
  function outportsm (line 388) | void outportsm(unsigned short port, unsigned char * data, unsigned long ...
  function ramfb_init (line 396) | static void ramfb_init(void) {
  function arch_framebuffer_initialize (line 501) | void arch_framebuffer_initialize(void) {
  function arch_enter_tasklet (line 522) | void arch_enter_tasklet(void) {
  function _spin_panic (line 530) | void _spin_panic(const char * lock_name, spin_lock_t * target) {
  function arch_spin_lock_acquire (line 540) | void arch_spin_lock_acquire(const char * name, spin_lock_t * target, con...
  function arch_spin_lock_release (line 577) | void arch_spin_lock_release(spin_lock_t * target) {

FILE: kernel/arch/aarch64/bootstub/main.c
  function swizzle (line 25) | static uint32_t swizzle(uint32_t from) {
  function swizzle64 (line 38) | static uint64_t swizzle64(uint64_t from) {
  function swizzle16 (line 50) | static uint16_t swizzle16(uint16_t from) {
  type fdt_header (line 56) | struct fdt_header {
  function dump_dtb (line 109) | static void dump_dtb(uintptr_t addr) {
  type fdt_header (line 161) | struct fdt_header
  type fdt_header (line 161) | struct fdt_header
  function base_cmp (line 170) | static int base_cmp(const char *a, const char *b) {
  function prefix_cmp (line 177) | static int prefix_cmp(const char *a, const char *b) {
  type fdt_header (line 210) | struct fdt_header
  type fdt_header (line 210) | struct fdt_header
  function _early_log_write (line 217) | static size_t _early_log_write(size_t size, uint8_t * buffer) {
  function _later_log_write (line 226) | static size_t _later_log_write(size_t size, uint8_t * buffer) {
  type BaseTables (line 235) | struct BaseTables {
  function bootstub_mmu_init (line 271) | static void bootstub_mmu_init(void) {
  function bootstub_read_kernel (line 341) | static void bootstub_read_kernel(uintptr_t kernel_load_addr) {
  function bootstub_load_kernel (line 427) | static void bootstub_load_kernel(Elf64_Header * header) {
  function bootstub_start_kernel (line 441) | static void bootstub_start_kernel(Elf64_Header * header) {
  function kmain (line 449) | int kmain(void) {

FILE: kernel/arch/aarch64/dtb.c
  function dtb_callback_direct_children (line 112) | void dtb_callback_direct_children(uint32_t * node, void (*callback)(uint...
  type fdt_header (line 119) | struct fdt_header
  type fdt_header (line 119) | struct fdt_header
  function base_cmp (line 128) | static int base_cmp(const char *a, const char *b) {
  function prefix_cmp (line 136) | static int prefix_cmp(const char *a, const char *b) {
  type fdt_header (line 169) | struct fdt_header
  type fdt_header (line 169) | struct fdt_header
  function dtb_memory_size (line 180) | void dtb_memory_size(size_t * memaddr, size_t * physsize) {
  function dtb_locate_cmdline (line 203) | void dtb_locate_cmdline(char ** args_out) {
  function dtb_pcie_base (line 214) | void dtb_pcie_base(void) {
  function read_dtb (line 228) | static ssize_t read_dtb(fs_node_t *node, off_t offset, size_t size, uint...
  function dtb_device (line 240) | void dtb_device(void) {

FILE: kernel/arch/aarch64/fwcfg.c
  type fwcfg_dma (line 20) | struct fwcfg_dma {
  function fwcfg_load_initrd (line 24) | __attribute__((aligned(4096)));
  function read_fwcfg (line 136) | static ssize_t read_fwcfg(fs_node_t * node, off_t offset, size_t size, u...
  function write_fwcfg (line 156) | static ssize_t write_fwcfg(fs_node_t * node, off_t offset, size_t size, ...
  function fwcfg_device (line 176) | void fwcfg_device(void) {

FILE: kernel/arch/aarch64/gic.c
  type irq_callback (line 21) | struct irq_callback
  function gic_map_regs (line 28) | void gic_map_regs(uintptr_t rpi_tag) {
  function gic_send_sgi (line 38) | void gic_send_sgi(uint8_t intid, int target) {
  function gic_assign_interrupt (line 46) | void gic_assign_interrupt(int irq, int (*callback)(process_t*,int,void*)...
  function gic_map_pci_interrupt (line 68) | void gic_map_pci_interrupt(const char * name, uint32_t device, int * int...

FILE: kernel/arch/aarch64/main.c
  type regs (line 38) | struct regs
  function arch_perf_timer (line 61) | uint64_t arch_perf_timer(void) {
  function arch_cpu_mhz (line 74) | size_t arch_cpu_mhz(void) {
  function arch_clock_initialize (line 85) | static void arch_clock_initialize(uintptr_t rpi_tag) {
  function update_ticks (line 108) | static void update_ticks(uint64_t ticks, uint64_t *timer_ticks, uint64_t...
  function gettimeofday (line 114) | int gettimeofday(struct timeval * t, void *z) {
  function now (line 123) | uint64_t now(void) {
  function settimeofday (line 131) | int settimeofday(struct timeval * t, void *z) {
  function relative_time (line 143) | void relative_time(unsigned long seconds, unsigned long subseconds, unsi...
  function set_tick (line 163) | static void set_tick(void) {
  function timer_start (line 174) | void timer_start(void) {
  function update_clock (line 204) | static void update_clock(void) {
  function _early_log_write (line 220) | static size_t _early_log_write(size_t size, uint8_t * buffer) {
  function early_log_initialize (line 227) | static void early_log_initialize(void) {
  function arch_set_core_base (line 233) | void arch_set_core_base(uintptr_t base) {
  function arch_set_tls_base (line 246) | void arch_set_tls_base(uintptr_t tlsbase) {
  function arch_set_kernel_stack (line 250) | void arch_set_kernel_stack(uintptr_t stack) {
  function exception_handlers (line 257) | static void exception_handlers(void) {
  function aarch64_sync_enter (line 263) | void aarch64_sync_enter(struct regs * r) {
  function spin (line 340) | static void spin(void) {
  function aarch64_interrupt_dispatch (line 349) | void aarch64_interrupt_dispatch(int from_wfi) {
  function aarch64_irq_enter (line 403) | void aarch64_irq_enter(struct regs * r) {
  function aarch64_fault_enter (line 416) | void aarch64_fault_enter(struct regs * r) {
  function aarch64_sp0_fault_enter (line 442) | void aarch64_sp0_fault_enter(struct regs * r) {
  function fpu_enable (line 455) | void fpu_enable(void) {
  function arch_pause (line 471) | void arch_pause(void) {
  function arch_clear_icache (line 493) | void arch_clear_icache(uintptr_t start, uintptr_t end) {
  function aarch64_processor_data (line 504) | void aarch64_processor_data(void) {
  function symbols_install (line 508) | static void symbols_install(void) {
  function kmain (line 526) | int kmain(uintptr_t dtb_base, uintptr_t phys_base, uintptr_t rpi_tag) {

FILE: kernel/arch/aarch64/mmu.c
  function mmu_frame_set (line 80) | void mmu_frame_set(uintptr_t frame_addr) {
  function mmu_frame_clear (line 94) | void mmu_frame_clear(uintptr_t frame_addr) {
  function mmu_frame_test (line 107) | int mmu_frame_test(uintptr_t frame_addr) {
  function mmu_frame_release (line 123) | void mmu_frame_release(uintptr_t frame_addr) {
  function mmu_first_n_frames (line 129) | uintptr_t mmu_first_n_frames(int n) {
  function mmu_first_frame (line 149) | uintptr_t mmu_first_frame(void) {
  function mmu_frame_allocate (line 176) | void mmu_frame_allocate(union PML * page, unsigned int flags) {
  function mmu_frame_map_address (line 215) | void mmu_frame_map_address(union PML * page, unsigned int flags, uintptr...
  function mmu_map_to_physical (line 269) | uintptr_t mmu_map_to_physical(union PML * root, uintptr_t virtAddr) {
  function copy_page_maybe (line 372) | static int copy_page_maybe(union PML * pt_in, union PML * pt_out, size_t...
  function mmu_allocate_a_frame (line 481) | uintptr_t mmu_allocate_a_frame(void) {
  function mmu_allocate_n_frames (line 489) | uintptr_t mmu_allocate_n_frames(int n) {
  function mmu_count_user (line 499) | size_t mmu_count_user(union PML * from) {
  function mmu_count_shm (line 534) | size_t mmu_count_shm(union PML * from) {
  function mmu_total_memory (line 566) | size_t mmu_total_memory(void) {
  function mmu_used_memory (line 570) | size_t mmu_used_memory(void) {
  function mmu_free (line 584) | void mmu_free(union PML * from) {
  function mmu_set_directory (line 637) | void mmu_set_directory(union PML * new_pml) {
  function mmu_invalidate (line 654) | void mmu_invalidate(uintptr_t addr) {
  function mmu_get_page_deep (line 657) | int mmu_get_page_deep(uintptr_t virtAddr, union PML ** pml4_out, union P...
  function maybe_release_directory (line 692) | static int maybe_release_directory(union PML * parent, union PML * child) {
  function mmu_unmap_user (line 710) | void mmu_unmap_user(uintptr_t addr, size_t size) {
  function mmu_unmap_module (line 817) | void mmu_unmap_module(uintptr_t start_address, size_t size) {
  function mmu_copy_on_write (line 820) | int mmu_copy_on_write(uintptr_t address) {
  function mmu_validate_user_pointer (line 825) | int mmu_validate_user_pointer(const void * addr, size_t size, int flags) {
  function k2p (line 858) | static uintptr_t k2p(void * x) {
  function mmu_init (line 862) | void mmu_init(uintptr_t memaddr, size_t memsize, uintptr_t firstFreePage...

FILE: kernel/arch/aarch64/pl011.c
  function pl011_irq (line 23) | static int pl011_irq(process_t * this, int irq, void * data) {
  function pl011_fill_name (line 36) | static void pl011_fill_name(pty_t * pty, char * name) {
  function pl011_write_out (line 40) | static void pl011_write_out(pty_t * pty, uint8_t c) {
  function pl011_thread (line 45) | static void pl011_thread(void * arg) {
  function pl011_start (line 73) | void pl011_start(void) {

FILE: kernel/arch/aarch64/rpi.c
  function rpi_load_ramdisk (line 22) | void rpi_load_ramdisk(struct rpitag * tag, uintptr_t * ramdisk_phys_base...
  function rpi_set_cmdline (line 50) | void rpi_set_cmdline(char ** args_out) {

FILE: kernel/arch/aarch64/rpi400/fbterm.c
  function set_point (line 39) | static inline void set_point(int x, int y, uint32_t value) {
  function fb_write_char (line 49) | static void fb_write_char(int _x, int _y, int val, uint32_t color) {
  function fb_get_width (line 92) | static int fb_get_width(void) {
  function fb_get_height (line 96) | static int fb_get_height(void) {
  function fb_scroll_terminal (line 100) | static void fb_scroll_terminal(void) {
  function draw_square (line 105) | static void draw_square(int x, int y) {
  function fbterm_draw_logo (line 116) | static void fbterm_draw_logo(void) {
  function fbterm_init_framebuffer (line 128) | static void fbterm_init_framebuffer(void) {
  function cursor_update (line 136) | static void cursor_update(void) {
  function process_char (line 151) | static void process_char(char ch) {
  function fbterm_write (line 257) | size_t fbterm_write(size_t size, uint8_t *buffer) {
  function fbterm_initialize (line 266) | void fbterm_initialize(void) {

FILE: kernel/arch/aarch64/rpi400/main.c
  function mmio_read32 (line 34) | static uint32_t mmio_read32(uintptr_t addr) {
  function mmio_write32 (line 38) | static void mmio_write32(uintptr_t addr, uint32_t val) {
  function mbox_call (line 42) | uint32_t mbox_call(uint8_t ch) {
  function rpi_fb_init (line 66) | int rpi_fb_init(void) {
  function rpi_cpu_freq (line 141) | void rpi_cpu_freq(void) {
  type BaseTables (line 195) | struct BaseTables {
  function bootstub_mmu_init (line 234) | static void bootstub_mmu_init(void) {
  function bootstub_load_kernel (line 306) | static void bootstub_load_kernel(Elf64_Header * header) {
  type rpitag (line 320) | struct rpitag
  function bootstub_start_kernel (line 322) | static void bootstub_start_kernel(uintptr_t dtb, Elf64_Header * header) {
  function bootstub_exit_el2 (line 330) | static void bootstub_exit_el2(void) {
  function kmain (line 386) | void kmain(uint32_t dtb_address, uint32_t base_addr) {

FILE: kernel/arch/aarch64/rpi_miniuart.c
  function mmio_read (line 26) | static uint32_t mmio_read(uintptr_t addr) {
  function mmio_write (line 30) | static void mmio_write(uintptr_t addr, uint32_t val) {
  function gpio_call (line 60) | static int gpio_call(uint32_t pin, uint32_t value, uint32_t base, uint32...
  function miniuart_irq (line 76) | static int miniuart_irq(process_t * this, int irq, void * data) {
  function miniuart_fill_name (line 90) | static void miniuart_fill_name(pty_t * pty, char * name) {
  function miniuart_write_out (line 94) | static void miniuart_write_out(pty_t * pty, uint8_t c) {
  function miniuart_thread (line 100) | static void miniuart_thread(void * arg) {
  function miniuart_start (line 150) | void miniuart_start(void) {

FILE: kernel/arch/aarch64/smp.c
  function ap_start (line 40) | void ap_start(uint64_t core_id) {
  function smp_bootstrap (line 67) | void smp_bootstrap(void) {
  function start_cpu (line 105) | static void start_cpu(uint32_t * node) {
  function aarch64_smp_start (line 143) | void aarch64_smp_start(void) {
  function rpi_smp_exit_el2 (line 195) | void rpi_smp_exit_el2(void) {
  function rpi_smp_init (line 215) | void rpi_smp_init(void) {

FILE: kernel/arch/aarch64/traceback.c
  function matching_symbol (line 21) | static uintptr_t matching_symbol(uintptr_t ip, char ** name) {
  function validate_pointer (line 38) | static int validate_pointer(uintptr_t base, size_t size) {
  type LoadedModule (line 60) | struct LoadedModule
  function aarch64_safe_dump_traceback (line 97) | void aarch64_safe_dump_traceback(uintptr_t elr, struct regs * r) {
  function arch_dump_traceback (line 110) | void arch_dump_traceback(void) {

FILE: kernel/arch/aarch64/virtio.c
  type virtio_device_cfg (line 27) | struct virtio_device_cfg {
  type virtio_common_cfg (line 44) | struct virtio_common_cfg {
  type virtio_buffer (line 66) | struct virtio_buffer {
  type virtio_avail (line 73) | struct virtio_avail {
  type virtio_ring (line 80) | struct virtio_ring {
  type virtio_used (line 85) | struct virtio_used {
  type virtio_queue (line 92) | struct virtio_queue {
  type virtio_input_event (line 98) | struct virtio_input_event {
  function virtio_tablet_responder (line 104) | int virtio_tablet_responder(process_t * this, int irq, void * data) {
  function virtio_keyboard_responder (line 113) | int virtio_keyboard_responder(process_t * this, int irq, void * data) {
  function try_to_get_boot_processor (line 122) | static void try_to_get_boot_processor(void) {
  function virtio_tablet_thread (line 133) | static void virtio_tablet_thread(void * data) {
  function virtio_keyboard_thread (line 303) | static void virtio_keyboard_thread(void * data) {
  function virtio_input_maybe (line 418) | static void virtio_input_maybe(uint32_t device, uint16_t v, uint16_t d, ...
  function null_input (line 429) | void null_input(void) {
  function virtio_input (line 444) | void virtio_input(void) {

FILE: kernel/arch/x86_64/cmos.c
  function cmos_dump (line 48) | static void cmos_dump(uint16_t * values) {
  function is_update_in_progress (line 58) | static int is_update_in_progress(void) {
  function secs_of_years (line 69) | static uint64_t secs_of_years(int years) {
  function secs_of_month (line 97) | static uint64_t secs_of_month(int months, int year) {
  function read_cmos (line 141) | uint64_t read_cmos(void) {
  function read_tsc (line 175) | static inline uint64_t read_tsc(void) {
  function arch_perf_timer (line 188) | uint64_t arch_perf_timer(void) {
  function arch_cpu_mhz (line 199) | size_t arch_cpu_mhz(void) {
  function arch_clock_initialize (line 221) | void arch_clock_initialize(void) {
  function update_ticks (line 291) | static void update_ticks(uint64_t ticks, uint64_t *timer_ticks, uint64_t...
  function gettimeofday (line 308) | int gettimeofday(struct timeval * t, void *z) {
  function now (line 322) | uint64_t now(void) {
  function settimeofday (line 336) | int settimeofday(struct timeval * t, void *z) {
  function relative_time (line 361) | void relative_time(unsigned long seconds, unsigned long subseconds, unsi...
  function arch_update_clock (line 389) | void arch_update_clock(void) {

FILE: kernel/arch/x86_64/gdt.c
  type tss_entry_t (line 18) | typedef struct tss_entry {
  type gdt_entry_t (line 28) | typedef struct {
  type gdt_entry_high_t (line 37) | typedef struct {
  type gdt_pointer_t (line 42) | typedef struct {
  function gdt_install (line 69) | void gdt_install(void) {
  function gdt_copy_to_trampoline (line 101) | void gdt_copy_to_trampoline(int ap, char * trampoline) {
  function arch_set_kernel_stack (line 105) | void arch_set_kernel_stack(uintptr_t stack) {
  function arch_set_tls_base (line 110) | void arch_set_tls_base(uintptr_t tlsbase) {

FILE: kernel/arch/x86_64/idt.c
  type idt_pointer (line 38) | struct idt_pointer
  function idt_set_gate (line 44) | void idt_set_gate(uint8_t num, interrupt_handler_t handler, uint16_t sel...
  function idt_install (line 58) | void idt_install(void) {
  function idt_ap_install (line 129) | void idt_ap_install(void) {
  function irq_install_handler (line 174) | void irq_install_handler(size_t irq, irq_handler_chain_t handler, const ...
  type LoadedModule (line 198) | struct LoadedModule
  type LoadedModule (line 204) | struct LoadedModule
  function validate_pointer (line 227) | static int validate_pointer(uintptr_t base, size_t size) {
  function matching_symbol (line 257) | static uintptr_t matching_symbol(uintptr_t ip, char ** name) {
  function dump_traceback (line 297) | static void dump_traceback(uintptr_t ip, uintptr_t bp) {
  function safe_dump_traceback (line 342) | static void safe_dump_traceback(struct regs * r) {
  function arch_dump_traceback (line 349) | void arch_dump_traceback(void) {
  function map_more_stack (line 360) | static int map_more_stack(uintptr_t fromAddr) {
  function panic (line 397) | static void panic(const char * desc, struct regs * r, uintptr_t faulting...
  function _debug_int (line 452) | static void _debug_int(struct regs * r) {
  function _double_fault (line 465) | static void _double_fault(struct regs * r) {
  function _general_protection_fault (line 477) | static void _general_protection_fault(struct regs * r) {
  function _page_fault (line 497) | static void _page_fault(struct regs * r) {
  function _local_timer (line 538) | static void _local_timer(struct regs * r) {
  function _exception (line 550) | static void _exception(struct regs * r, const char * description, int si...
  function _handle_irq (line 566) | static void _handle_irq(struct regs * r, int irq) {
  function isr_handler_inner (line 580) | void isr_handler_inner(struct regs * r) {
  function isr_handler (line 649) | void isr_handler(struct regs * r) {
  function syscall_centry (line 664) | void syscall_centry(struct regs * r) {

FILE: kernel/arch/x86_64/main.c
  type multiboot (line 51) | struct multiboot
  function _early_log_write (line 56) | static size_t _early_log_write(size_t size, uint8_t * buffer) {
  function early_log_initialize (line 65) | static void early_log_initialize(void) {
  type MB2_TagHeader (line 73) | struct MB2_TagHeader {
  type MB2_TagHeader (line 81) | struct MB2_TagHeader
  type MB2_MemoryMap (line 98) | struct MB2_MemoryMap {
  type MB2_MemoryMap_Entry (line 105) | struct MB2_MemoryMap_Entry {
  type MB2_Framebuffer (line 112) | struct MB2_Framebuffer {
  type MB2_Module (line 122) | struct MB2_Module {
  function multiboot2_initialize (line 129) | static void multiboot2_initialize(void * mboot) {
  function multiboot_initialize (line 159) | static void multiboot_initialize(struct multiboot * mboot) {
  function mboot_unmark_valid_memory (line 195) | void mboot_unmark_valid_memory(void) {
  function symbols_install (line 224) | static void symbols_install(uint64_t base) {
  function pat_initialize (line 239) | void pat_initialize(void) {
  function fpu_initialize (line 260) | void fpu_initialize(void) {
  function mount_ramdisk (line 281) | static void mount_ramdisk(uintptr_t addr, size_t len) {
  function mount_multiboot_ramdisks (line 325) | void mount_multiboot_ramdisks(struct multiboot * mboot) {
  type loader (line 350) | struct loader { uint32_t type; uint32_t size; char name[]; }
  type loader (line 365) | struct loader { uint32_t type; uint32_t size; char name[]; }
  function arch_set_core_base (line 378) | void arch_set_core_base(uintptr_t base) {
  function arch_framebuffer_initialize (line 384) | void arch_framebuffer_initialize(void) {
  function kmain (line 414) | int kmain(struct multiboot * mboot, uint32_t mboot_mag, void* esp, uint6...

FILE: kernel/arch/x86_64/mmu.c
  function mmu_frame_set (line 62) | void mmu_frame_set(uintptr_t frame_addr) {
  function mmu_frame_clear (line 82) | void mmu_frame_clear(uintptr_t frame_addr) {
  function mmu_frame_test (line 100) | int mmu_frame_test(uintptr_t frame_addr) {
  function mmu_frame_release (line 114) | void mmu_frame_release(uintptr_t frame_addr) {
  function mmu_first_n_frames (line 125) | uintptr_t mmu_first_n_frames(int n) {
  function mmu_first_frame (line 148) | uintptr_t mmu_first_frame(void) {
  function mmu_frame_allocate (line 176) | void mmu_frame_allocate(union PML * page, unsigned int flags) {
  function mmu_frame_map_address (line 197) | void mmu_frame_map_address(union PML * page, unsigned int flags, uintptr...
  function mmu_map_to_physical (line 269) | uintptr_t mmu_map_to_physical(union PML * root, uintptr_t virtAddr) {
  function refcount_inc (line 388) | int refcount_inc(uintptr_t frame) {
  function refcount_dec (line 408) | uint8_t refcount_dec(uintptr_t frame) {
  function copy_page_maybe (line 441) | int copy_page_maybe(union PML * pt_in, union PML * pt_out, size_t l, uin...
  function free_page_maybe (line 504) | int free_page_maybe(union PML * pt_in, size_t l, uintptr_t address) {
  function mmu_allocate_a_frame (line 611) | uintptr_t mmu_allocate_a_frame(void) {
  function mmu_allocate_n_frames (line 624) | uintptr_t mmu_allocate_n_frames(int n) {
  function mmu_count_user (line 647) | size_t mmu_count_user(union PML * from) {
  function mmu_count_shm (line 689) | size_t mmu_count_shm(union PML * from) {
  function mmu_total_memory (line 725) | size_t mmu_total_memory(void) {
  function mmu_used_memory (line 737) | size_t mmu_used_memory(void) {
  function mmu_free (line 759) | void mmu_free(union PML * from) {
  function mmu_set_directory (line 817) | void mmu_set_directory(union PML * new_pml) {
  function mmu_invalidate (line 835) | void mmu_invalidate(uintptr_t addr) {
  function mmu_get_page_deep (line 842) | int mmu_get_page_deep(uintptr_t virtAddr, union PML ** pml4_out, union P...
  function maybe_release_directory (line 877) | static int maybe_release_directory(union PML * parent, union PML * child) {
  function mmu_unmap_user (line 895) | void mmu_unmap_user(uintptr_t addr, size_t size) {
  function mmu_init (line 942) | void mmu_init(size_t memsize, uintptr_t firstFreePage) {
  function mmu_unmap_module (line 1180) | void mmu_unmap_module(uintptr_t start_address, size_t size) {
  function mmu_copy_on_write (line 1216) | int mmu_copy_on_write(uintptr_t address) {
  function mmu_validate_user_pointer (line 1275) | int mmu_validate_user_pointer(const void * addr, size_t size, int flags) {

FILE: kernel/arch/x86_64/pic.c
  function irq_remap (line 41) | static void irq_remap(void) {
  function irq_ack (line 59) | void irq_ack(size_t irq_no) {
  function pic_initialize (line 66) | void pic_initialize(void) {

FILE: kernel/arch/x86_64/pit.c
  function pit_set_timer_phase (line 39) | static void pit_set_timer_phase(long hz) {
  function pit_interrupt (line 49) | int pit_interrupt(struct regs *r) {
  function pit_initialize (line 64) | void pit_initialize(void) {

FILE: kernel/arch/x86_64/ports.c
  function inports (line 12) | unsigned short inports(unsigned short _port) {
  function outports (line 18) | void outports(unsigned short _port, unsigned short _data) {
  function inportl (line 22) | unsigned int inportl(unsigned short _port) {
  function outportl (line 28) | void outportl(unsigned short _port, unsigned int _data) {
  function inportb (line 32) | unsigned char inportb(unsigned short _port) {
  function outportb (line 38) | void outportb(unsigned short _port, unsigned char _data) {
  function outportsm (line 42) | void outportsm(unsigned short port, unsigned char * data, unsigned long ...
  function inportsm (line 46) | void inportsm(unsigned short port, unsigned char * data, unsigned long s...

FILE: kernel/arch/x86_64/ps2hid.c
  function ps2_wait_input (line 73) | static int ps2_wait_input(void) {
  function ps2_wait_output (line 86) | static int ps2_wait_output(void) {
  function ps2_command (line 97) | static void ps2_command(uint8_t cmdbyte) {
  function ps2_command_response (line 105) | static uint8_t ps2_command_response(uint8_t cmdbyte) {
  function ps2_command_arg (line 115) | static void ps2_command_arg(uint8_t cmdbyte, uint8_t arg) {
  function mouse_write (line 125) | static uint8_t mouse_write(uint8_t write) {
  function ps2_read_byte (line 134) | static uint8_t ps2_read_byte(void) {
  function kbd_write (line 142) | static uint8_t kbd_write(uint8_t write) {
  function finish_packet (line 156) | static void finish_packet(void) {
  function ps2_mouse_handle (line 207) | static void ps2_mouse_handle(uint8_t data_byte) {
  function ioctl_mouse (line 238) | static int ioctl_mouse(fs_node_t * node, unsigned long request, void * a...
  function ps2_kbd_handle (line 253) | static void ps2_kbd_handle(uint8_t data_byte) {
  function shared_handler (line 271) | static int shared_handler(struct regs * r) {
  function keyboard_handler (line 297) | static int keyboard_handler(struct regs *r) {
  function mouse_handler (line 307) | static int mouse_handler(struct regs *r) {
  function ps2hid_install (line 318) | void ps2hid_install(void) {

FILE: kernel/arch/x86_64/serial.c
  type serial_port_map (line 33) | struct serial_port_map {
  type serial_port_map (line 41) | struct serial_port_map
  type serial_port_map (line 48) | struct serial_port_map
  function pty_t (line 58) | static pty_t ** pty_for_port(int port) {
  function serial_rcvd (line 62) | static int serial_rcvd(int device) {
  function serial_recv (line 66) | static char serial_recv(int device) {
  function serial_transmit_empty (line 71) | static int serial_transmit_empty(int device) {
  function serial_send (line 75) | static void serial_send(int device, char out) {
  function process_serial (line 83) | static void process_serial(void * argp) {
  function serial_handler_ac (line 114) | int serial_handler_ac(struct regs *r) {
  function serial_handler_bd (line 120) | int serial_handler_bd(struct regs *r) {
  type divisor (line 128) | struct divisor {
  function serial_enable (line 141) | static void serial_enable(int port, tcflag_t cflags) {
  function serial_write_out (line 179) | static void serial_write_out(pty_t * pty, uint8_t c) {
  function serial_fill_name (line 190) | static void serial_fill_name(pty_t * pty, char * name) {
  function fs_node_t (line 194) | static fs_node_t * serial_device_create(int port) {
  function serial_initialize (line 223) | void serial_initialize(void) {

FILE: kernel/arch/x86_64/smp.c
  function __ap_bootstrap (line 23) | __attribute__((used))
  function __ap_bootstrap_landing (line 70) | __attribute__((used))
  function read_tsc (line 110) | static inline uint64_t read_tsc(void) {
  function short_delay (line 121) | static void short_delay(unsigned long amount) {
  function load_processor_info (line 139) | void load_processor_info(void) {
  function lapic_timer_initialize (line 180) | static void lapic_timer_initialize(void) {
  function ap_main (line 207) | void ap_main(void) {
  function lapic_write (line 250) | void lapic_write(size_t addr, uint32_t value) {
  function lapic_read (line 260) | uint32_t lapic_read(size_t addr) {
  function lapic_send_ipi (line 272) | void lapic_send_ipi(int i, uint32_t val) {
  function xtoi (line 287) | uintptr_t xtoi(const char * c) {
  function smp_initialize (line 315) | void smp_initialize(void) {
  function arch_wakeup_others (line 493) | void arch_wakeup_others(void) {
  function arch_tlb_shootdown (line 509) | void arch_tlb_shootdown(uintptr_t vaddr) {

FILE: kernel/arch/x86_64/user.c
  function arch_enter_user (line 31) | void arch_enter_user(uintptr_t entrypoint, int argc, char * argv[], char...
  function _kill_it (line 53) | static void _kill_it(void) {
  function arch_return_from_signal_handler (line 73) | int arch_return_from_signal_handler(struct regs *r) {
  function arch_enter_signal_handler (line 117) | void arch_enter_signal_handler(uintptr_t entrypoint, int signum, struct ...
  function arch_resume_user (line 167) | __attribute__((naked))
  function arch_restore_floating (line 195) | void arch_restore_floating(process_t * proc) {
  function arch_save_floating (line 202) | void arch_save_floating(process_t * proc) {
  function arch_pause (line 213) | void arch_pause(void) {
  function arch_fatal_prepare (line 234) | void arch_fatal_prepare(void) {
  function arch_fatal (line 245) | void arch_fatal(void) {
  function arch_reboot (line 264) | long arch_reboot(void) {
  function arch_syscall_return (line 282) | void arch_syscall_return(struct regs * r, long retval) { r->rax = retval; }
  function arch_syscall_number (line 283) | long arch_syscall_number(struct regs * r) { return (unsigned long)r->rax; }
  function arch_syscall_arg0 (line 284) | long arch_syscall_arg0(struct regs * r) { return r->rdi; }
  function arch_syscall_arg1 (line 285) | long arch_syscall_arg1(struct regs * r) { return r->rsi; }
  function arch_syscall_arg2 (line 286) | long arch_syscall_arg2(struct regs * r) { return r->rdx; }
  function arch_syscall_arg3 (line 287) | long arch_syscall_arg3(struct regs * r) { return r->r10; }
  function arch_syscall_arg4 (line 288) | long arch_syscall_arg4(struct regs * r) { return r->r8; }
  function arch_stack_pointer (line 289) | long arch_stack_pointer(struct regs * r) { return r->rsp; }
  function arch_user_ip (line 290) | long arch_user_ip(struct regs * r) { return r->rip; }

FILE: kernel/audio/snd.c
  type dsp_node (line 70) | struct dsp_node {
  function snd_register (line 77) | int snd_register(snd_device_t * device) {
  function snd_unregister (line 94) | int snd_unregister(snd_device_t * device) {
  function snd_dsp_write (line 109) | static ssize_t snd_dsp_write(fs_node_t * node, off_t offset, size_t size...
  function snd_dsp_ioctl (line 126) | static int snd_dsp_ioctl(fs_node_t * node, unsigned long request, void *...
  function snd_dsp_open (line 137) | static void snd_dsp_open(fs_node_t * node, unsigned int flags) {
  function snd_dsp_close (line 155) | static void snd_dsp_close(fs_node_t * node) {
  function snd_device_t (line 166) | static snd_device_t * snd_device_by_id(uint32_t device_id) {
  function snd_mixer_ioctl (line 182) | static int snd_mixer_ioctl(fs_node_t * node, unsigned long request, void...
  function snd_mixer_open (line 232) | static void snd_mixer_open(fs_node_t * node, unsigned int flags) {
  function snd_mixer_close (line 236) | static void snd_mixer_close(fs_node_t * node) {
  function snd_request_buf (line 240) | int snd_request_buf(snd_device_t * device, uint32_t size, uint8_t *buffe...
  function snd_device_t (line 276) | static snd_device_t * snd_main_device(void) {
  function snd_install (line 287) | void snd_install(void) {

FILE: kernel/binfmt.c
  function exec_shebang (line 27) | int exec_shebang(const char * path, fs_node_t * file, int argc, char *co...
  type exec_def_t (line 85) | typedef struct {
  function matches (line 97) | static int matches(unsigned char * a, unsigned char * b, unsigned int le...
  function exec (line 114) | int exec(const char * path, int argc, char *const argv[], char *const en...
  function system (line 138) | int system(const char * path, int argc, char *const argv[], char *const ...

FILE: kernel/generic.c
  function generic_startup (line 38) | void generic_startup(void) {
  function generic_main (line 57) | int generic_main(void) {

FILE: kernel/misc/args.c
  function args_present (line 48) | int args_present(const char * karg) {
  function args_parse (line 66) | void args_parse(const char * cmdline) {

FILE: kernel/misc/assert.c
  function __assert_failed (line 14) | void __assert_failed(const char * file, int line, const char * func, con...

FILE: kernel/misc/elf64.c
  function modules_install (line 33) | void modules_install(void) {
  function hashmap_t (line 38) | hashmap_t * modules_get_list(void) {
  function aarch64_imm_adr (line 45) | static uint32_t aarch64_imm_adr(uint32_t val) {
  function aarch64_imm_12 (line 54) | static uint32_t aarch64_imm_12(uint32_t val) {
  function elf_module (line 58) | int elf_module(char ** args) {
  function elf_exec (line 251) | int elf_exec(const char * path, fs_node_t * file, int argc, const char *...

FILE: kernel/misc/fbterm.c
  function set_point (line 45) | static inline void set_point(int x, int y, uint32_t value) {
  function fb_write_char (line 59) | static void fb_write_char(int _x, int _y, int val, uint32_t color) {
  function fb_get_
Condensed preview — 787 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,353K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 17,
    "preview": "github: [klange]\n"
  },
  {
    "path": ".github/SECURITY.md",
    "chars": 2090,
    "preview": "# Reporting Vulnerabilities and Exploits\n\nAs ToaruOS is not intended for serious real-world use, responsible disclosure "
  },
  {
    "path": ".github/workflows/aarch64.yml",
    "chars": 1078,
    "preview": "on: [push, workflow_dispatch]\nname: QEMU AArch64 virt\njobs:\n  build-image:\n    runs-on: ubuntu-latest\n    steps:\n      -"
  },
  {
    "path": ".github/workflows/x86_64.yml",
    "chars": 1756,
    "preview": "on: [push, workflow_dispatch]\nname: x86-64 CD Image\njobs:\n  build-image:\n    runs-on: ubuntu-latest\n    steps:\n      - n"
  },
  {
    "path": ".gitignore",
    "chars": 434,
    "preview": "*.aux\n*.idx\n*.ilg\n*.ind\n*.log\n*.o\n*.a\n*.out\n*.pdf\n*.so\n*.swp\n*.swn\n*.toc\n*.ko\n*.pcap\n.gdb_history\n/ramdisk.tar\n/ramdisk."
  },
  {
    "path": ".gitmodules",
    "chars": 225,
    "preview": "[submodule \"util/binutils-gdb\"]\n\tpath = util/binutils-gdb\n\turl = ../../toaruos/binutils-gdb\n[submodule \"util/gcc\"]\n\tpath"
  },
  {
    "path": ".mailmap",
    "chars": 663,
    "preview": "K. Lange <klange@toaruos.org>\nK. Lange <klange@toaruos.org> <klange@dakko.us>\nK. Lange <klange@toaruos.org> <k@dakko.us>"
  },
  {
    "path": "AUTHORS",
    "chars": 398,
    "preview": "Maintainer and Author:\n\n    K. Lange\n\nMajor Contributors:\n\n    Mike Gerow\n    Dale Weiler\n    Matt White\n    Markus Scho"
  },
  {
    "path": "LICENSE",
    "chars": 1624,
    "preview": "\nUniversity of Illinois/NCSA Open Source License\n\nCopyright (c) 2011-2022 K Lange, et al. (hereafter [fullname]). All ri"
  },
  {
    "path": "Makefile",
    "chars": 8129,
    "preview": "# ToaruOS 2.0 root Makefile\nTOOLCHAIN=util\nBASE=base\nexport PATH := $(shell $(TOOLCHAIN)/activate.sh)\n\nARCH ?= $(shell $"
  },
  {
    "path": "README.md",
    "chars": 14997,
    "preview": "# ToaruOS\n\nToaruOS is a \"complete\" operating system for x86-64 PCs and experimental support for ARMv8.\n\nWhile many indep"
  },
  {
    "path": "apps/about.c",
    "chars": 6243,
    "preview": "/**\n * @brief about - Show an \"About <Application>\" dialog.\n *\n * By default, shows \"About ToaruOS\", suitable for use as"
  },
  {
    "path": "apps/basename.c",
    "chars": 680,
    "preview": "/**\n * @brief basename - print file name\n *\n * @copyright\n * This file is part of ToaruOS and is released under the term"
  },
  {
    "path": "apps/beep.c",
    "chars": 2720,
    "preview": "/**\n * @brief Implementation of the 'beep' utility.\n *\n * I've tried to get the functionality here as close to the commo"
  },
  {
    "path": "apps/bim.c",
    "chars": 353337,
    "preview": "/* Bim - A Text Editor\n *\n * Copyright (C) 2012-2026 K. Lange\n *\n * Permission to use, copy, modify, and/or distribute t"
  },
  {
    "path": "apps/bim.h",
    "chars": 15132,
    "preview": "#ifndef _BIM_CORE_H\n#define _BIM_CORE_H\n\n#define _XOPEN_SOURCE 700\n#define _DARWIN_C_SOURCE\n#define _DEFAULT_SOURCE\n#inc"
  },
  {
    "path": "apps/block-dev-stats.c",
    "chars": 916,
    "preview": "/**\n * @brief Show block device statistics, where available.\n *\n * Shows cache hit/miss/write counts for ATA devices, mo"
  },
  {
    "path": "apps/cal.c",
    "chars": 2058,
    "preview": "/**\n * @brief cal - print a calendar\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n *"
  },
  {
    "path": "apps/calculator.c",
    "chars": 13435,
    "preview": "/**\n * @file apps/calculator.c\n * @brief Four-function calculator app.\n *\n * This calculator app is intended to be a mor"
  },
  {
    "path": "apps/cat-img.c",
    "chars": 3904,
    "preview": "/**\n * @brief Display images in a Toaru terminal.\n *\n * @copyright\n * This file is part of ToaruOS and is released under"
  },
  {
    "path": "apps/cat.c",
    "chars": 1506,
    "preview": "/**\n * @brief cat - Concatenate files\n *\n * Concatenates files together to standard output.\n * In a supporting terminal,"
  },
  {
    "path": "apps/chmod.c",
    "chars": 2674,
    "preview": "/**\n * @brief chmod - change file permissions\n *\n * This implementation is likely non-compliant, though it does\n * attem"
  },
  {
    "path": "apps/chown.c",
    "chars": 2469,
    "preview": "/**\n * @brief chown - bad implementation thereof\n *\n * @copyright\n * This file is part of ToaruOS and is released under "
  },
  {
    "path": "apps/clear.c",
    "chars": 570,
    "preview": "/**\n * @brief clear - Clear the terminal\n *\n * Sends an escape code to clear the screen. Ideally, this should\n * come fr"
  },
  {
    "path": "apps/cmp.c",
    "chars": 2495,
    "preview": "/**\n * @brief Compare files\n *\n * Standard POSIX utility.\n *\n * XXX Only use this with normal files; errors in special f"
  },
  {
    "path": "apps/color-picker.c",
    "chars": 12843,
    "preview": "/**\n * @file apps/color-picker.c\n * @brief Color picker\n *\n * Color Picker widget demo, eventually maybe a paint app aga"
  },
  {
    "path": "apps/compositor.c",
    "chars": 98777,
    "preview": "/**\n * @brief Yutani - The ToaruOS Window Compositor.\n *\n * Yutani is a canvas-based window compositor and manager.\n * I"
  },
  {
    "path": "apps/cp.c",
    "chars": 5298,
    "preview": "/**\n * @brief cp - Copy files\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n * of the"
  },
  {
    "path": "apps/cpu-name.krk",
    "chars": 1095,
    "preview": "#!/bin/kuroko\n\nimport fileio\n\nlet lines\nlet cpus = {0: {}}\nlet current = 0\n\nwith fileio.open('/proc/cpuinfo','r') as f:\n"
  },
  {
    "path": "apps/cpuwidget.c",
    "chars": 19317,
    "preview": "/**\n * @brief System monitor tool\n *\n * Displays CPU usage, memory usage, and network usage, with nice\n * curvy anti-ali"
  },
  {
    "path": "apps/crc32.c",
    "chars": 4174,
    "preview": "/**\n * crc32 - Simple CRC32 calculator for verifying file integrity.\n *\n * @copyright\n * This file is part of ToaruOS an"
  },
  {
    "path": "apps/cursor-off.c",
    "chars": 898,
    "preview": "/**\n * @brief cursor-off - Disables the VGA text mode cursor.\n *\n * This is an old tool that calls a special system call"
  },
  {
    "path": "apps/date.c",
    "chars": 3758,
    "preview": "/**\n * date - Print the current date and time.\n *\n * TODO: The traditional POSIX version of this tool is supposed\n *    "
  },
  {
    "path": "apps/dbg.c",
    "chars": 18943,
    "preview": "/**\n * @brief Debugger.\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n * of the NCSA "
  },
  {
    "path": "apps/demo.c",
    "chars": 1861,
    "preview": "/**\n * @brief Simple executable that was used during initial testing of Misaka.\n *\n * @copyright\n * This file is part of"
  },
  {
    "path": "apps/demo.krk",
    "chars": 131,
    "preview": "#!/bin/kuroko\nimport os, kuroko\n\nprint('Kuroko',kuroko.version, kuroko.buildenv, kuroko.builddate)\nprint('Running on:',o"
  },
  {
    "path": "apps/dhclient.c",
    "chars": 11248,
    "preview": "/**\n * @brief DHCP client\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n * of the NCS"
  },
  {
    "path": "apps/dirname.c",
    "chars": 500,
    "preview": "/**\n * @brief dirname - print directory name from path string\n *\n * @copyright\n * This file is part of ToaruOS and is re"
  },
  {
    "path": "apps/drawlines.c",
    "chars": 3119,
    "preview": "/**\n * @brief drawlines - Draw random lines into a GUI window\n *\n * The original compositor demo application, this dates"
  },
  {
    "path": "apps/du.c",
    "chars": 2916,
    "preview": "/**\n * @brief du - calculate file size usage\n *\n * TODO: Should use st_blocks, but we don't set that in the kernel yet?\n"
  },
  {
    "path": "apps/echo.c",
    "chars": 2354,
    "preview": "/**\n * @brief echo - Print arguments to stdout.\n *\n * Prints arguments to stdout, possibly interpreting escape\n * sequen"
  },
  {
    "path": "apps/env.c",
    "chars": 940,
    "preview": "/**\n * @brief env - Print or set environment\n *\n * @copyright\n * This file is part of ToaruOS and is released under the "
  },
  {
    "path": "apps/esh.c",
    "chars": 55286,
    "preview": "/**\n * @brief E-Shell\n *\n * This is \"experimental shell\" - a vaguely-unix-like command\n * interface. It has a very rudim"
  },
  {
    "path": "apps/false.c",
    "chars": 260,
    "preview": "/**\n * @brief false - returns a failure status code.\n *\n * @copyright\n * This file is part of ToaruOS and is released un"
  },
  {
    "path": "apps/fetch.c",
    "chars": 10795,
    "preview": "/**\n * @file  apps/fetch.c\n * @brief Obtain files over HTTP.\n *\n * @copyright\n * This file is part of ToaruOS and is rel"
  },
  {
    "path": "apps/file-browser.c",
    "chars": 76597,
    "preview": "/**\n * @brief Graphical file browser\n * @file apps/file-browser.c\n *\n * Based on the original Python implementation and "
  },
  {
    "path": "apps/find-timezone.c",
    "chars": 1194,
    "preview": "/**\n * @brief Query a remote API to get timezone information based geoip lookup.\n *\n * We ask @see ip-api.com for geo-ip"
  },
  {
    "path": "apps/font-preview.c",
    "chars": 5335,
    "preview": "/**\n * @brief TrueType font previewer\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n "
  },
  {
    "path": "apps/font-tool.c",
    "chars": 2833,
    "preview": "/**\n * @file apps/font-tool.c\n * @brief Print information about TrueType fonts.\n *\n * @copyright\n * This file is part of"
  },
  {
    "path": "apps/free.c",
    "chars": 1775,
    "preview": "/**\n * @brief free - Show free / used / total RAM\n *\n * @copyright\n * This file is part of ToaruOS and is released under"
  },
  {
    "path": "apps/getty.c",
    "chars": 1772,
    "preview": "/**\n * @brief getty - Manage a TTY.\n *\n * Wraps a serial port (or other dumb connection) with a pty\n * and manages a log"
  },
  {
    "path": "apps/glogin-provider.c",
    "chars": 14374,
    "preview": "/**\n * @brief Graphical login display.\n *\n * Called by @ref glogin to show a graphical login prompt.\n *\n * @copyright\n *"
  },
  {
    "path": "apps/glogin.c",
    "chars": 3038,
    "preview": "/**\n * @brief Graphical login daemon.\n *\n * Launches graphical login windows and manages login sessions.\n *\n * @copyrigh"
  },
  {
    "path": "apps/grep.c",
    "chars": 17588,
    "preview": "/**\n * @brief grep - almost acceptable grep\n *\n * Based on the regex search matcher in bim.\n *\n * @copyright\n * This fil"
  },
  {
    "path": "apps/groups.c",
    "chars": 860,
    "preview": "/**\n * @brief List group memberships.\n * @file apps/groups.c\n *\n * @copyright\n * This file is part of ToaruOS and is rel"
  },
  {
    "path": "apps/gsudo.c",
    "chars": 7880,
    "preview": "/**\n * @brief gsudo - graphical implementation of sudo\n *\n * probably even less secure than the original\n *\n * @copyrigh"
  },
  {
    "path": "apps/gunzip.c",
    "chars": 3435,
    "preview": "/**\n * @brief gunzip - decompress gzip-compressed payloads\n *\n * @copyright\n * This file is part of ToaruOS and is relea"
  },
  {
    "path": "apps/head.c",
    "chars": 1351,
    "preview": "/**\n * @brief head - Print the first `n` lines of a file.\n *\n * @copyright\n * This file is part of ToaruOS and is releas"
  },
  {
    "path": "apps/hello.c",
    "chars": 324,
    "preview": "/**\n * @brief hello - Prints \"Hello, world.\"\n *\n * @copyright\n * This file is part of ToaruOS and is released under the "
  },
  {
    "path": "apps/help-browser.c",
    "chars": 16529,
    "preview": "/**\n * @brief help-browser - Display documentation.\n *\n * This is a work-in-progress reimplementation of the help browse"
  },
  {
    "path": "apps/hexify.c",
    "chars": 5611,
    "preview": "/**\n * @brief hexify - Convert binary to hex.\n *\n * This is based on the output of xxd.\n *\n * @copyright\n * This file is"
  },
  {
    "path": "apps/highlight-source.krk",
    "chars": 266,
    "preview": "#!/bin/kuroko\nimport fileio, syntax.highlighter, kuroko\n\nlet code\nwith fileio.open(kuroko.argv[-1]) as f:\n    code = f.r"
  },
  {
    "path": "apps/hostname.c",
    "chars": 815,
    "preview": "/**\n * @brief hostname - Prints or sets the system hostname.\n *\n * @copyright\n * This file is part of ToaruOS and is rel"
  },
  {
    "path": "apps/ifconfig.c",
    "chars": 6804,
    "preview": "/**\n * @file  apps/ifconfig.c\n * @brief Network interface configuration tool.\n *\n * Manipulates and enumerates network i"
  },
  {
    "path": "apps/imgviewer.c",
    "chars": 7225,
    "preview": "/**\n * @brief imgviewer - Display bitmaps in a graphical window.\n *\n * This is probably the 4th time I've (re)written a "
  },
  {
    "path": "apps/init.c",
    "chars": 3897,
    "preview": "/**\n * @brief init - First process.\n *\n * `init` calls startup scripts and then waits for them to complete.\n * It also w"
  },
  {
    "path": "apps/insmod.c",
    "chars": 620,
    "preview": "/**\n * @brief insmod - Load kernel module\n *\n * @copyright\n * This file is part of ToaruOS and is released under the ter"
  },
  {
    "path": "apps/irc.c",
    "chars": 11290,
    "preview": "/**\n * @brief irc - Internet Relay Chat client\n *\n * @copyright\n * This file is part of ToaruOS and is released under th"
  },
  {
    "path": "apps/json-test.c",
    "chars": 2570,
    "preview": "/**\n * @brief Test suite for the JSON library.\n *\n * @copyright\n * This file is part of ToaruOS and is released under th"
  },
  {
    "path": "apps/julia.c",
    "chars": 16501,
    "preview": "/**\n * @brief julia - Julia Fractal Generator\n *\n * Displays Julia fractals in a window. Use the keyboard\n * to navigate"
  },
  {
    "path": "apps/kbd-test.c",
    "chars": 1746,
    "preview": "/**\n * @brief Keyboard test tool\n *\n * XXX This probably doesn't work anymore. It uses the VGA text mode\n *     region b"
  },
  {
    "path": "apps/kcmdline.c",
    "chars": 1880,
    "preview": "/**\n * @brief kcmdline - Parse /proc/cmdline usefully.\n *\n * Parses /proc/cmdline and provides an interface for querying"
  },
  {
    "path": "apps/kill.c",
    "chars": 2674,
    "preview": "/**\n * @brief kill - Send a signal to a process\n *\n * Supports signal names like any mature `kill` should.\n *\n * @copyri"
  },
  {
    "path": "apps/killall.c",
    "chars": 4571,
    "preview": "/**\n * @brief killall - Send signals to processes matching name\n *\n * Find processes by name and send them signals.\n *\n "
  },
  {
    "path": "apps/krk_test_noise.krk",
    "chars": 1043,
    "preview": "#!/bin/kuroko\nimport os\nimport gc\nif 'KUROKO_TEST_ENV' in os.environ:\n    return 0\n\nfrom time import sleep\nfrom fileio i"
  },
  {
    "path": "apps/krk_yutani_test.krk",
    "chars": 5709,
    "preview": "#!/bin/kuroko\nfrom _yutani2 import (YutaniCtx, Font, rgb, rgb, MenuBar, decor_get_bounds, decor_render,\n                "
  },
  {
    "path": "apps/live-session.c",
    "chars": 1384,
    "preview": "/**\n * @brief live-session - Run live CD user session.\n *\n * Launches the general session manager as 'local', waits for "
  },
  {
    "path": "apps/ln.c",
    "chars": 1342,
    "preview": "/**\n * @brief Make symlinks\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n * of the N"
  },
  {
    "path": "apps/login-loop.c",
    "chars": 4351,
    "preview": "/**\n * @brief Repeatedly invoke `login` in a loop.\n *\n * This is more closely related to the 'getty' command in Linux\n *"
  },
  {
    "path": "apps/login.c",
    "chars": 3088,
    "preview": "/**\n * @brief TTY login prompt\n *\n * Provides the user with a login prompt and starts their session.\n *\n * @copyright\n *"
  },
  {
    "path": "apps/logname.c",
    "chars": 492,
    "preview": "/**\n * @brief Display the user's name, as returned by getlogin()\n *\n * @copyright\n * This file is part of ToaruOS and is"
  },
  {
    "path": "apps/ls.c",
    "chars": 11494,
    "preview": "/**\n * @brief List files\n *\n * Lists files in a directory, with nice color\n * output like any modern ls should have.\n *\n"
  },
  {
    "path": "apps/lspci.c",
    "chars": 9065,
    "preview": "/**\n * lspci - Print information about connected PCI devices.\n *\n * @copyright\n * This file is part of ToaruOS and is re"
  },
  {
    "path": "apps/maybe-pdfviewer.krk",
    "chars": 442,
    "preview": "#!/bin/kuroko\nimport os\nimport kuroko\n\ntry:\n    os.stat('/usr/bin/pdfviewer')\n    os.execl('/usr/bin/pdfviewer','pdfview"
  },
  {
    "path": "apps/migrate.c",
    "chars": 5669,
    "preview": "/**\n * @brief migrate - Relocate root filesystem to tmpfs\n *\n * Run as part of system startup to move the ext2 root ramd"
  },
  {
    "path": "apps/mines.krk",
    "chars": 13201,
    "preview": "#!/bin/kuroko\n'''\nMinesweeper game\n\nOriginally written in Python and ported to Kuroko.\nVisual design is based on the Gno"
  },
  {
    "path": "apps/misaka-test.c",
    "chars": 1689,
    "preview": "/**\n * @file  apps/misaka-test.c\n * @brief Test app for Misaka with a bunch of random stuff.\n * @copyright\n * This file "
  },
  {
    "path": "apps/mixerctl.c",
    "chars": 3251,
    "preview": "/**\n * @brief Control audio mixer knobs\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms"
  },
  {
    "path": "apps/mkdir.c",
    "chars": 1358,
    "preview": "/**\n * @brief Create directories\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n * of "
  },
  {
    "path": "apps/mktemp.c",
    "chars": 1348,
    "preview": "/**\n * @brief mktemp - create a temporary directory and print its name\n *\n * @copyright\n * This file is part of ToaruOS "
  },
  {
    "path": "apps/more.c",
    "chars": 4624,
    "preview": "/**\n * @brief Print piped input or files one screenful at a time.\n *\n * @copyright\n * This file is part of ToaruOS and i"
  },
  {
    "path": "apps/mount.c",
    "chars": 607,
    "preview": "/**\n * @brief Mount filesystems into the VFS\n *\n * @copyright\n * This file is part of ToaruOS and is released under the "
  },
  {
    "path": "apps/msk.c",
    "chars": 14150,
    "preview": "/**\n * @brief Package Management Utility for ToaruOS\n *\n * This is a not-quite-faithful reconstruction of the original\n "
  },
  {
    "path": "apps/mv.c",
    "chars": 2833,
    "preview": "/**\n * @brief Move files\n *\n * Poor implementation, mostly just 'cp' and 'rm'.\n *\n * Ideally, should figure out if it ca"
  },
  {
    "path": "apps/netty.c",
    "chars": 3088,
    "preview": "/**\n * @brief Provides a PTY over a reverse network socket.\n *\n * Pipes data into and out of a PTY from a TCP socket con"
  },
  {
    "path": "apps/nproc.c",
    "chars": 385,
    "preview": "/**\n * @brief Print the number of available processors.\n *\n * @copyright\n * This file is part of ToaruOS and is released"
  },
  {
    "path": "apps/nslookup.c",
    "chars": 730,
    "preview": "/**\n * @brief Perform DNS lookups.\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n * o"
  },
  {
    "path": "apps/nyancat/animation.h",
    "chars": 52846,
    "preview": "/*\n * Pop Tart Cat animation frames\n */\n#ifndef ANIMATION_H\n#define ANIMATION_H\n\nconst char * frame0[] = {\n\",,,,,,,,,,,,"
  },
  {
    "path": "apps/nyancat/telnet.h",
    "chars": 2842,
    "preview": "#ifndef TELNET_H\n#define TELNET_H\n\n/* Telnet Defines */\n#define IAC   255\n#define DONT  254\n#define DO    253\n#define WO"
  },
  {
    "path": "apps/nyancat.c",
    "chars": 29119,
    "preview": "/*\n * Copyright (c) 2011-2018 K. Lange.  All rights reserved.\n *\n * Developed by:            K. Lange\n *                "
  },
  {
    "path": "apps/package-manager.c",
    "chars": 21797,
    "preview": "/**\n * @brief Graphical interface to msk\n *\n * @copyright\n * This file is part of ToaruOS and is released under the term"
  },
  {
    "path": "apps/panel.c",
    "chars": 26266,
    "preview": "/**\n * @file apps/panel.c\n * @brief Panel with widgets. Main desktop interface.\n *\n * Provides the panel shown at the to"
  },
  {
    "path": "apps/path_demo.krk",
    "chars": 7541,
    "preview": "#!/bin/kuroko\nfrom _yutani2 import (YutaniCtx, Font, rgb, MenuBar, decor_get_bounds, decor_render,\n                     "
  },
  {
    "path": "apps/piano.c",
    "chars": 1760,
    "preview": "/**\n * @brief piano - Interactively make beeping noises\n *\n * @copyright\n * This file is part of ToaruOS and is released"
  },
  {
    "path": "apps/pidof.c",
    "chars": 2281,
    "preview": "/**\n * @brief Look up the PIDs of all processes with a particular name\n *\n * @copyright\n * This file is part of ToaruOS "
  },
  {
    "path": "apps/ping.c",
    "chars": 4588,
    "preview": "/**\n * @brief Send ICMP pings\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n * of the"
  },
  {
    "path": "apps/plasma.c",
    "chars": 5177,
    "preview": "/**\n * @brief Threaded graphical demo that draws animated plasma.\n *\n * Good for burning CPU.\n *\n * @copyright\n * This f"
  },
  {
    "path": "apps/play.c",
    "chars": 1785,
    "preview": "/**\n * @brief play - Play back PCM samples\n *\n * This needs very specifically-formatted PCM data to function\n * properly"
  },
  {
    "path": "apps/polygons.c",
    "chars": 9844,
    "preview": "/**\n * @brief Draw filled polygons from line segments.\n *\n * This is an older version of the polygon rasterizer that tur"
  },
  {
    "path": "apps/pong.c",
    "chars": 7470,
    "preview": "/**\n * @brief pong - Window Manager Pong\n *\n * Play pong where the paddles and ball are all windows.\n * Use the WM bindi"
  },
  {
    "path": "apps/prompt_and_delete.krk",
    "chars": 1004,
    "preview": "#!/bin/kuroko\nimport kuroko\nimport os\nimport _waitpid\nlet count = len(kuroko.argv)\n\nif count < 3:\n    print(\"expected at"
  },
  {
    "path": "apps/ps.c",
    "chars": 7667,
    "preview": "/**\n * @brief Print a list of running processes.\n *\n * The listed processes are limited to ones owned by the current\n * "
  },
  {
    "path": "apps/pstree.c",
    "chars": 3591,
    "preview": "/**\n * @brief pstree - Display a tree of running process\n *\n * @copyright\n * This file is part of ToaruOS and is release"
  },
  {
    "path": "apps/pwd.c",
    "chars": 402,
    "preview": "/**\n * @brief Print the current working directory\n *\n * @copyright\n * This file is part of ToaruOS and is released under"
  },
  {
    "path": "apps/qemu-display-hack.c",
    "chars": 1850,
    "preview": "/**\n * @brief qemu-display-hack - Manage display size under QEMU\n *\n * XXX Does this still work? Does the TTY interface "
  },
  {
    "path": "apps/qemu-fwcfg.c",
    "chars": 4343,
    "preview": "/**\n * @brief qemu-fwcfg - Read QEMU fwcfg values.\n *\n * Provides easy access to values and files set by QEMU's -fw_cfg\n"
  },
  {
    "path": "apps/readelf.c",
    "chars": 22893,
    "preview": "/**\n * @file  readelf.c\n * @brief Display information about a 64-bit Elf binary or object.\n *\n * Implementation of a `re"
  },
  {
    "path": "apps/readlink.c",
    "chars": 688,
    "preview": "/**\n * @brief Examine symlinks and print the path they point to.\n *\n * @copyright\n * This file is part of ToaruOS and is"
  },
  {
    "path": "apps/reboot.c",
    "chars": 488,
    "preview": "/**\n * @brief (Try to) reboot the system.\n *\n * Note that only root can syscall_reboot, and this doesn't\n * do any fancy"
  },
  {
    "path": "apps/reload_desktop.sh",
    "chars": 113,
    "preview": "#!/bin/esh\n\nexport-cmd DESKTOP cat /var/run/.wallpaper.pid\n\nif not empty? \"$DESKTOP\" then kill -SIGUSR2 $DESKTOP\n"
  },
  {
    "path": "apps/reset.c",
    "chars": 441,
    "preview": "/**\n * @brief reset - make the terminal sane, and clear it\n *\n * Also clears scrollback!\n *\n * @copyright\n * This file i"
  },
  {
    "path": "apps/rm.c",
    "chars": 2126,
    "preview": "/**\n * @brief rm - Unlink files\n *\n * TODO: Support recursive, directory removal, etc.\n *\n * @copyright\n * This file is "
  },
  {
    "path": "apps/rmdir.c",
    "chars": 1618,
    "preview": "/**\n * @brief rmdir - remove empty directories\n *\n * @copyright\n * This file is part of ToaruOS and is released under th"
  },
  {
    "path": "apps/serial-console.c",
    "chars": 2979,
    "preview": "/**\n * @brief serial console\n *\n * Old tool for poking serial ports. Probably doesn't work right\n * anymore since serial"
  },
  {
    "path": "apps/session.c",
    "chars": 1132,
    "preview": "/**\n * @brief session - UI session manager\n *\n * Runs the user's yutanirc or starts up a panel and desktop\n * if they do"
  },
  {
    "path": "apps/set-resolution.c",
    "chars": 1236,
    "preview": "/**\n * @brief set-resolution - Change the display resolution.\n *\n * @copyright\n * This file is part of ToaruOS and is re"
  },
  {
    "path": "apps/set-wallpaper.sh",
    "chars": 324,
    "preview": "#!/bin/esh\n\nif empty? \"$1\" then exec sh -c \"echo 'usage: $0 WALLPAPER'\"\nif not stat -Lq \"$1\" then exec sh -c \"echo '$0: "
  },
  {
    "path": "apps/show-toasts.krk",
    "chars": 1301,
    "preview": "#!/bin/kuroko\nimport kuroko\nimport os\nimport fileio\nimport time\n\ntime.sleep(2)\n\ntry:\n    let meminfo = {}\n\n    let data\n"
  },
  {
    "path": "apps/show-tutorial.sh",
    "chars": 64,
    "preview": "#!/bin/sh\n\ntouch ~/.tutorial-shown\nsh -c \"sleep 1; tutorial\" &\n\n"
  },
  {
    "path": "apps/showdialog.c",
    "chars": 8079,
    "preview": "/**\n * @brief showdialog - show a window with a dialog prompt with buttons\n *\n * @copyright\n * This file is part of Toar"
  },
  {
    "path": "apps/sleep.c",
    "chars": 676,
    "preview": "/**\n * @brief sleep - Do nothing, efficiently.\n *\n * @copyright\n * This file is part of ToaruOS and is released under th"
  },
  {
    "path": "apps/snow.c",
    "chars": 4197,
    "preview": "/**\n * @brief Draw pretty falling snowflakes.\n *\n * @copyright\n * This file is part of ToaruOS and is released under the"
  },
  {
    "path": "apps/sort.c",
    "chars": 2061,
    "preview": "/**\n * @brief Sort input lines.\n *\n * XXX for reasons unknown this is using its own insertion-sort\n *     instead of our"
  },
  {
    "path": "apps/splash-log.c",
    "chars": 3716,
    "preview": "/**\n * @brief Console log manager.\n *\n * Presents a PEX endpoint for startup processes to write log\n * messages to and w"
  },
  {
    "path": "apps/stat.c",
    "chars": 3325,
    "preview": "/**\n * @brief Display file status.\n *\n * The format for this is terrible and we're missing a bunch\n * of data we provide"
  },
  {
    "path": "apps/strace.c",
    "chars": 34480,
    "preview": "/**\n * @brief Process system call tracer.\n *\n * @copyright\n * This file is part of ToaruOS and is released under the ter"
  },
  {
    "path": "apps/strings.c",
    "chars": 1893,
    "preview": "/**\n * @brief strings - print printable character sequences found in a file\n *\n * @copyright\n * This file is part of Toa"
  },
  {
    "path": "apps/stty.c",
    "chars": 12570,
    "preview": "/**\n * @brief Set and display tty config bits.\n *\n * Surprisingly complete.\n *\n * We used to use Minix's stty, so I may "
  },
  {
    "path": "apps/sudo.c",
    "chars": 4439,
    "preview": "/**\n * @brief sudo - Run processes as the root user, after authenticating.\n *\n * Our sudo supports cached authentication"
  },
  {
    "path": "apps/sync.c",
    "chars": 1143,
    "preview": "/**\n * @brief Wait for filesystem buffered writes to finish.\n *\n * And by \"wait\" and \"to finish\" I mean \"tell the block "
  },
  {
    "path": "apps/sysfunc.c",
    "chars": 658,
    "preview": "/**\n * @brief Exceute \"extended system function\" syscalls.\n *\n * Most of these are deprecated, and the ones that are use"
  },
  {
    "path": "apps/sysinfo.c",
    "chars": 4743,
    "preview": "/**\n * @brief Display system information.\n *\n * Similar to tools like 'screenfetch', this displays information\n * about "
  },
  {
    "path": "apps/t_mbstowcs.c",
    "chars": 623,
    "preview": "/**\n * @brief Test tool for libc UTF8 decoding\n *\n * @copyright\n * This file is part of ToaruOS and is released under th"
  },
  {
    "path": "apps/tar.c",
    "chars": 10478,
    "preview": "/**\n * @brief tar - extract archives\n *\n * This is a very minimal and incomplete implementation of tar.\n * It supports o"
  },
  {
    "path": "apps/tee.c",
    "chars": 1246,
    "preview": "/**\n * @brief tee - copy stdin to stdout and to specified files\n *\n * @copyright\n * This file is part of ToaruOS and is "
  },
  {
    "path": "apps/terminal-font.h",
    "chars": 117307,
    "preview": "/**\n * @file apps/terminal-font.h\n * @brief Fallback font used to render text where the TrueType renderer would be inapp"
  },
  {
    "path": "apps/terminal-palette.h",
    "chars": 4514,
    "preview": "/**\n * @file apps/terminal-palette.h\n * @brief Terminal color palette\n *\n * Provides the color table for both the basic "
  },
  {
    "path": "apps/terminal-vga.c",
    "chars": 35573,
    "preview": "/**\n * @brief Virtual terminal emulator, for VGA text mode.\n *\n * Basicall the same as @ref terminal.c but outputs to th"
  },
  {
    "path": "apps/terminal.c",
    "chars": 79482,
    "preview": "/**\n * @brief Virtual terminal emulator.\n *\n * Provides a graphical character cell terminal with support for\n * antialia"
  },
  {
    "path": "apps/test-badwrite.c",
    "chars": 499,
    "preview": "/**\n * @brief Test tool for examining a bug that was crashing the audio subsystem.\n *\n * @copyright\n * This file is part"
  },
  {
    "path": "apps/test-conf.c",
    "chars": 668,
    "preview": "/**\n * @brief Test tool for the INI confreader library.\n *\n * @copyright\n * This file is part of ToaruOS and is released"
  },
  {
    "path": "apps/test-fpclassify.c",
    "chars": 466,
    "preview": "#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <math.h>\n\nint main(int argc, cha"
  },
  {
    "path": "apps/test-ftruncate.c",
    "chars": 2088,
    "preview": "/**\n * @brief Quick spot check of ftruncate\n *\n * @copyright\n * This file is part of ToaruOS and is released under the t"
  },
  {
    "path": "apps/test-localtime.c",
    "chars": 774,
    "preview": "/**\n * @brief Test tool for the libc localtime() function.\n *\n * @copyright\n * This file is part of ToaruOS and is relea"
  },
  {
    "path": "apps/test-lock.c",
    "chars": 942,
    "preview": "/**\n * @brief Test tool for filesystem locks (O_EXCL)\n *\n * @copyright\n * This file is part of ToaruOS and is released u"
  },
  {
    "path": "apps/test-loop.c",
    "chars": 315,
    "preview": "/**\n * @brief Spins in a loop. Useful for testing preemption, cpu usage.\n *\n * @copyright\n * This file is part of ToaruO"
  },
  {
    "path": "apps/test-printf.c",
    "chars": 447,
    "preview": "/**\n * @brief Test tool for libc printf formatters.\n *\n * @copyright\n * This file is part of ToaruOS and is released und"
  },
  {
    "path": "apps/test-ptrace-syscall.c",
    "chars": 1609,
    "preview": "#include <errno.h>\n#include <string.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <getopt.h>\n#in"
  },
  {
    "path": "apps/test-sigsegv.c",
    "chars": 540,
    "preview": "/**\n * @brief Test tool for producing segmentation faults.\n *\n * Useful for testing the debugger.\n *\n * @copyright\n * Th"
  },
  {
    "path": "apps/test-sigsuspend.c",
    "chars": 674,
    "preview": "#include <stdio.h>\n#include <signal.h>\n#include <errno.h>\n#include <string.h>\n#include <unistd.h>\n\nvoid handler(int sig)"
  },
  {
    "path": "apps/test-sigwait.c",
    "chars": 512,
    "preview": "#include <stdio.h>\n#include <signal.h>\n#include <errno.h>\n#include <string.h>\n\nvoid handler(int sig) {\n\tfprintf(stderr, "
  },
  {
    "path": "apps/test-syscall-sysret.c",
    "chars": 598,
    "preview": "#include <unistd.h>\n#include <stdio.h>\n#include <syscall_nums.h>\n\nint main(int argc, char * argv[]){\n\tlong ret = 0;\n#ifd"
  },
  {
    "path": "apps/test-tls.c",
    "chars": 1179,
    "preview": "/**\n * @brief Test tool for thread local storage.\n *\n * @copyright\n * This file is part of ToaruOS and is released under"
  },
  {
    "path": "apps/test-tty-read.c",
    "chars": 1092,
    "preview": "#include <string.h>\n#include <stdio.h>\n#include <termios.h>\n#include <unistd.h>\n#include <signal.h>\n\nstruct termios old;"
  },
  {
    "path": "apps/test-udp-recv.krk",
    "chars": 194,
    "preview": "#!/bin/kuroko\nimport socket\n\nlet s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n\nprint(\"Binding to :1234\")\ns.bind("
  },
  {
    "path": "apps/toaru_logo.h",
    "chars": 5727,
    "preview": "/**\n * @file apps/toaru_logo.sh\n * @brief Generated by GIMP, ToaruOS logo\n *\n * Used by sysinfo. Can be used by other th"
  },
  {
    "path": "apps/toast.krk",
    "chars": 1236,
    "preview": "#!/bin/kuroko\nimport kuroko\nimport os\n\ndef jsonFilter(c):\n    let mapping = {\n        '\"': '\\\\\"',\n        '\\\\': '\\\\\\\\',\n"
  },
  {
    "path": "apps/toastd.c",
    "chars": 6858,
    "preview": "/**\n * @brief Toast notification daemon.\n * @file  apps/toastd.c\n *\n * Provides an endpoint for applications to post not"
  },
  {
    "path": "apps/toggle-abs-mouse.c",
    "chars": 1311,
    "preview": "/**\n * @brief toggle-abs-mouse - Toggle mouse modes\n *\n * Set the mouse mode under VirtualBox, VMware, or QEMU to either"
  },
  {
    "path": "apps/top.c",
    "chars": 21312,
    "preview": "/**\n * @brief Show processes sorted by resource usage.\n *\n * @copyright\n * This file is part of ToaruOS and is released "
  },
  {
    "path": "apps/touch.c",
    "chars": 645,
    "preview": "/**\n * @brief touch - Create or update file timestamps\n *\n * @copyright\n * This file is part of ToaruOS and is released "
  },
  {
    "path": "apps/true.c",
    "chars": 248,
    "preview": "/**\n * @brief true - Return success code\n *\n * @copyright\n * This file is part of ToaruOS and is released under the term"
  },
  {
    "path": "apps/tty.c",
    "chars": 436,
    "preview": "/**\n * @brief tty - print terminal name\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms"
  },
  {
    "path": "apps/ttysize.c",
    "chars": 2311,
    "preview": "/**\n * @brief ttysize - Magically divine terminal size\n *\n * This is called by getty to determine the size of foreign\n *"
  },
  {
    "path": "apps/tutorial.c",
    "chars": 15992,
    "preview": "/**\n * @brief A recreation of the original wizard.py, explaining\n *        the functionality of ToaruOS and how to use t"
  },
  {
    "path": "apps/uname.c",
    "chars": 2936,
    "preview": "/**\n * @brief uname - Print kernel version information\n *\n * Supports all the usual options (a,s,n,r,v,m,o)\n *\n * Note t"
  },
  {
    "path": "apps/ununicode.h",
    "chars": 4072,
    "preview": "/* Commonly used by a few different things. */\nstatic uint32_t ununicode(uint32_t c) {\n\tswitch (c) {\n\t\tcase L'☺': return"
  },
  {
    "path": "apps/upload.krk",
    "chars": 801,
    "preview": "#!/bin/kuroko\n'''\nTest tool to send file contents over a socket.\n\n$ upload.krk file address:port\n'''\nimport socket\nimpor"
  },
  {
    "path": "apps/uptime.c",
    "chars": 2105,
    "preview": "/**\n * @brief Print system uptime\n *\n * @copyright\n * This file is part of ToaruOS and is released under the terms\n * of"
  },
  {
    "path": "apps/vga-palette.h",
    "chars": 8152,
    "preview": "/**\n * @brief VGA palette conversion\n *\n * Converts 256-color index values to closest matching 16-color\n * value for the"
  },
  {
    "path": "apps/wallpaper-picker.c",
    "chars": 12235,
    "preview": "/**\n * @brief Graphical wallpaper picker.\n *\n * @copyright\n * This file is part of ToaruOS and is released under the ter"
  },
  {
    "path": "apps/wc.c",
    "chars": 2835,
    "preview": "/**\n * @brief wc - count bytes, characters, words, lines...\n *\n * @copyright\n * This file is part of ToaruOS and is rele"
  },
  {
    "path": "apps/weather-configurator.c",
    "chars": 1693,
    "preview": "/**\n * @brief Configure the weather information 'daemon'\n *\n * Messes with /etc/weather.json so it needs root for now..."
  },
  {
    "path": "apps/weather-tool.c",
    "chars": 4058,
    "preview": "/**\n * @brief Ask OpenWeather for forecast data.\n *\n * Fetches weather forecast data from OpenWeather and converts the J"
  },
  {
    "path": "apps/which.c",
    "chars": 1673,
    "preview": "/**\n * @brief which - Figure out which binary will be used\n *\n * Searches through $PATH to find a matching binary, just "
  },
  {
    "path": "apps/whoami.c",
    "chars": 524,
    "preview": "/**\n * @brief uses getpwuid and geteuid to retrieve the current user's name.\n *\n * @copyright\n * This file is part of To"
  },
  {
    "path": "apps/yes.c",
    "chars": 477,
    "preview": "/**\n * @brief yes - Continually print stuff\n *\n * Continually prints its first argument, followed by a newline.\n *\n * @c"
  },
  {
    "path": "apps/yutani-clipboard.c",
    "chars": 2727,
    "preview": "/**\n * @brief yutani-clipboard - Manipulate the Yutani clipboard\n *\n * Gets and sets clipboard values.\n *\n * @copyright\n"
  },
  {
    "path": "apps/yutani-kbd.c",
    "chars": 2473,
    "preview": "/**\n * @brief Debug tool for keyboard input.\n *\n * @copyright\n * This file is part of ToaruOS and is released under the "
  },
  {
    "path": "apps/yutani-query.c",
    "chars": 1959,
    "preview": "/**\n * @brief yutani-query - Query display server information\n *\n * At the moment, this only supports querying the displ"
  },
  {
    "path": "apps/yutani-test.c",
    "chars": 5206,
    "preview": "/**\n * @brief yutani-test - Yutani Test Tool\n *\n * Kinda like xev: Pops up a window and displays events in a\n * human-re"
  },
  {
    "path": "apps/yutani-tty-pipe.c",
    "chars": 1679,
    "preview": "#include <stdio.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/ioctl.h>\n#include <termios.h>\n\n#include <toaru/y"
  },
  {
    "path": "apps/zcat.c",
    "chars": 317,
    "preview": "#include <unistd.h>\n#include <stdlib.h>\n\nint main(int argc, char * argv[]) {\n\tchar ** args = malloc(sizeof(char*) * (arg"
  },
  {
    "path": "base/etc/demo.conf",
    "chars": 74,
    "preview": "; this is a comment\ntest=hello\n\n[sec]\ntion=test\n\n; this is also a comment\n"
  },
  {
    "path": "base/etc/group",
    "chars": 42,
    "preview": "root:x:0:\nadm:x:1:local\ndialout:x:2:local\n"
  },
  {
    "path": "base/etc/hostname",
    "chars": 7,
    "preview": "livecd\n"
  },
  {
    "path": "base/etc/master.passwd",
    "chars": 174,
    "preview": "root:toor:0:0:Administrator:/home/root:/bin/esh:fancy\nlocal:local:1000:1000:Local User:/home/local:/bin/esh:fancy\nguest:"
  },
  {
    "path": "base/etc/motd",
    "chars": 186,
    "preview": "\n\u001b[1;33mWelcome to ToaruOS!\u001b[0m\n\nToaruOS is free software, released under the terms\nof the NCSA / University of Illinois"
  },
  {
    "path": "base/etc/msk.conf",
    "chars": 192,
    "preview": "remote_order=cdrom,cdn,fallback\n\n[remotes]\ncdrom=/cdrom/extra\nlocal=http://192.168.11.2:8080\nfallback=http://toaruos.org"
  },
  {
    "path": "base/etc/panel.menu",
    "chars": 749,
    "preview": ":_\n&accessories,folder,Accessories\n&demos,folder,Demos\n&games,folder,Games\n&settings,folder,Settings\n-\nexec help-browser"
  }
]

// ... and 587 more files (download for full content)

About this extraction

This page contains the full source code of the klange/toaruos GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 787 files (3.8 MB), approximately 1.0M tokens, and a symbol index with 5110 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!