Compare commits

...
5 Commits
Author SHA1 Message Date
Burer ef1eceaa6c data: point the desktop menu to TASKMAN
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 21s
Test PR / Build (en_US) (pull_request) Successful in 2m56s
Test PR / Build (ru_RU) (pull_request) Successful in 3m1s
Test PR / Build (es_ES) (pull_request) Successful in 3m1s
Assisted-by: Claude:claude-opus-5-5
2026-10-04 09:25:15 +03:00
Burer 3f3770fc57 apps/taskman: add a readme
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 20s
Test PR / Build (en_US) (pull_request) Successful in 1m51s
Test PR / Build (es_ES) (pull_request) Successful in 1m57s
Test PR / Build (ru_RU) (pull_request) Successful in 2m1s
Assisted-by: Claude:claude-opus-5-5
2026-10-03 22:36:40 +03:00
Burer 9fe9b676c1 data: replace CPU and SYSMON with TASKMAN
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 24s
Test PR / Build (en_US) (pull_request) Successful in 2m10s
Test PR / Build (es_ES) (pull_request) Successful in 2m16s
Test PR / Build (ru_RU) (pull_request) Successful in 2m23s
Put TASKMAN in the image instead of CPU and SYSMON and point the
menu, the system panel and the KolibriNext dock and desktop to it.

Assisted-by: Claude:claude-opus-5-5
2026-10-03 22:02:00 +03:00
Burer 3110deedd5 kernel: start TASKMAN on Ctrl+Alt+Del
Assisted-by: Claude:claude-opus-5-5
2026-10-03 22:01:59 +03:00
Burer 0486f294ce apps/taskman: add a task manager
One program with five tabs instead of CPU and SYSMON:

- Processes: threads with CPU and memory, sortable; Details, End,
  Run..., system threads on request.
- Performance: CPU, temperature, memory and network graphs; the CPU
  sensor (Intel, AMD, Hygon, VIA, Zhaoxin) or a board chip.
- Disks: partitions with labels, used space of memory disks; Open.
- Drivers: drivers loaded by the kernel; Load...
- Autorun: /sys/settings/autorun.dat, a program turned on or off.

The window and lists follow the system colors; en_US, ru_RU, es_ES.
The kpacked binary fits in 12 sectors.

Assisted-by: Claude:claude-opus-5-5
2026-10-03 22:01:59 +03:00
29 changed files with 3826 additions and 17 deletions

No files matched your search

+1 -2
View File
@@ -421,7 +421,6 @@ tup.append_table(img_files, {
{"CALENDAR", VAR_PROGS .. "/system/calendar/calendar"},
{"COLRDIAL", VAR_PROGS .. "/system/colrdial/color_dialog"},
{"CROPFLAT", VAR_PROGS .. "/system/cropflat/cropflat"},
{"CPU", VAR_PROGS .. "/system/cpu/cpu"},
{"CPUID", VAR_PROGS .. "/testing/cpuid/CPUID"},
{"DOCPACK", VAR_PROGS .. "/system/docpack/docpack"},
{"DEFAULT.SKN", VAR_SKINS .. "/../skins/Leency/Shkvorka/Shkvorka.skn"},
@@ -446,6 +445,7 @@ tup.append_table(img_files, {
{"SCRSHOOT", VAR_PROGS .. "/media/scrshoot/scrshoot"},
{"SETUP", VAR_PROGS .. "/system/setup/setup"},
{"SKINCFG", VAR_PROGS .. "/system/skincfg/skincfg"},
{"TASKMAN", VAR_PROGS .. "/system/taskman/taskman"},
{"TERMINAL", VAR_PROGS .. "/system/terminal/terminal"},
{"TEST", VAR_PROGS .. "/testing/protection/test"},
{"TINYPAD", VAR_PROGS .. "/develop/tinypad/tinypad"},
@@ -694,7 +694,6 @@ tup.append_table(img_files, {
{"BBENCH", VAR_PROGS .. "/cmm/bbench/bbench.com"},
{"SEARCH", VAR_PROGS .. "/cmm/misc/search.com"},
{"SYSPANEL", VAR_PROGS .. "/cmm/misc/software_widget.com"},
{"SYSMON", VAR_PROGS .. "/cmm/sysmon/sysmon.com"},
{"TMPDISK", VAR_PROGS .. "/cmm/tmpdisk/tmpdisk.com"},
{"DEVELOP/CLIPVIEW", VAR_PROGS .. "/cmm/clipview/clipview.com"},
{"DEVELOP/MENU", VAR_PROGS .. "/cmm/menu/menu.com"},
+1 -1
View File
@@ -1 +1 @@
[@] location=3 fsize=0 ashow=1 [AppPlus] path=/sys/app_plus param= icon=27 $=1 [KFAR] path=/sys/file managers/kfar param= icon=16 [Pixie2] path=/sys/media/pixie param= icon=65 [IconEdit] path=/sys/media/iconedit param= icon=98 [Calc] path=/sys/calc param= icon=4 [Notes] path=/kolibrios/utils/notes param= icon=117 [Dictionary] path=/kolibrios/utils/dicty.kex param= icon=79 [FB2Read] path=/sys/fb2read param= icon=44 [Animage] path=/sys/media/animage param= icon=15 [RDSave] path=/sys/rdsave param= icon=17 $=1 [Volume] path=/sys/@volume param= icon=64 [NetStatus] path=/sys/network/netstat param= icon=33 [SysMon] path=/sys/sysmon param= icon=57 [SysPanel] path=/sys/syspanel param= icon=6
[@] location=3 fsize=0 ashow=1 [AppPlus] path=/sys/app_plus param= icon=27 $=1 [KFAR] path=/sys/file managers/kfar param= icon=16 [Pixie2] path=/sys/media/pixie param= icon=65 [IconEdit] path=/sys/media/iconedit param= icon=98 [Calc] path=/sys/calc param= icon=4 [Notes] path=/kolibrios/utils/notes param= icon=117 [Dictionary] path=/kolibrios/utils/dicty.kex param= icon=79 [FB2Read] path=/sys/fb2read param= icon=44 [Animage] path=/sys/media/animage param= icon=15 [RDSave] path=/sys/rdsave param= icon=17 $=1 [Volume] path=/sys/@volume param= icon=64 [NetStatus] path=/sys/network/netstat param= icon=33 [TaskMan] path=/sys/taskman param= icon=57 [SysPanel] path=/sys/syspanel param= icon=6
+1 -1
View File
@@ -1 +1 @@
[rbmenu] Диспетчер процессов=/sys/cpu Настройка внешнего вида=/kolibrios/utils/appearance ;Настройка цветов=/sys/skincfg ;Сплошной фон=/sys/media/palitra [01] name=FILES path=/sys/File Managers/EOLITE param= ico=7 x=4 y=21 [02] name=FPLAY path=/kolibrios/media/fplay param= ico=96 x=65 y=21 [03] name=GAMES path=/sys/allgames param= ico=35 x=125 y=21 [04] name=TINYPAD path=/sys/tinypad param= ico=9 x=4 y=96 [05] name=zSEA path=/kolibrios/media/zsea/zsea param= ico=46 x=65 y=96 [06] name=WEBVIEW path=/sys/network/webview param= ico=31 x=125 y=96 ; ========= ; RIGHT TOP ; ========= [10] name=DEBUG path=/SYS/DEVELOP/MTDBG param= ico=39 x=-204 y=21 [11] name=BOARD path=/SYS/DEVELOP/BOARD param= ico=19 x=-140 y=21 [12] name=KPACK path=/SYS/KPACK param= ico=99 x=-77 y=21 [13] name=DIFF path=/sys/develop/diff param= ico=84 x=-203 y=96 [14] name=FASM path=/SYS/DEVELOP/FASM param= ico=10 x=-141 y=96 [15] name=DOCPACK path=/sys/network/webview param=/kolibrios/res/guide/guide.htm ico=8 x=-76 y=96 [16] name=SHELL path=/SYS/SHELL param= ico=1 x=-203 y=166 [17] name=HEXEDIT path=/SYS/DEVELOP/HEED param= ico=22 x=-141 y=166 [18] name=CEDIT path=/sys/develop/cedit param= ico=58 x=-74 y=166
[rbmenu] Диспетчер задач=/sys/taskman Настройка внешнего вида=/kolibrios/utils/appearance ;Настройка цветов=/sys/skincfg ;Сплошной фон=/sys/media/palitra [01] name=FILES path=/sys/File Managers/EOLITE param= ico=7 x=4 y=21 [02] name=FPLAY path=/kolibrios/media/fplay param= ico=96 x=65 y=21 [03] name=GAMES path=/sys/allgames param= ico=35 x=125 y=21 [04] name=TINYPAD path=/sys/tinypad param= ico=9 x=4 y=96 [05] name=zSEA path=/kolibrios/media/zsea/zsea param= ico=46 x=65 y=96 [06] name=WEBVIEW path=/sys/network/webview param= ico=31 x=125 y=96 ; ========= ; RIGHT TOP ; ========= [10] name=DEBUG path=/SYS/DEVELOP/MTDBG param= ico=39 x=-204 y=21 [11] name=BOARD path=/SYS/DEVELOP/BOARD param= ico=19 x=-140 y=21 [12] name=KPACK path=/SYS/KPACK param= ico=99 x=-77 y=21 [13] name=DIFF path=/sys/develop/diff param= ico=84 x=-203 y=96 [14] name=FASM path=/SYS/DEVELOP/FASM param= ico=10 x=-141 y=96 [15] name=DOCPACK path=/sys/network/webview param=/kolibrios/res/guide/guide.htm ico=8 x=-76 y=96 [16] name=SHELL path=/SYS/SHELL param= ico=1 x=-203 y=166 [17] name=HEXEDIT path=/SYS/DEVELOP/HEED param= ico=22 x=-141 y=166 [18] name=CEDIT path=/sys/develop/cedit param= ico=58 x=-74 y=166
+1 -2
View File
@@ -23,8 +23,7 @@ Bus Disconnect=kbd,37
System Settings=setup,5
[Monitoring]
Processes=cpu,60
System Monitor=sysmon,57
Task Manager=taskman,57
Ghost Monitor=gmon,107
Network Status=network/netstat,33
AMDtemp=/k/utils/AMDtemp,128
+1 -1
View File
@@ -1,5 +1,5 @@
[rbmenu]
Processes=cpu
Task manager=taskman
Theme settings=skincfg
Background=/sys/media/palitra
System panel=syspanel
+1 -1
View File
@@ -75,7 +75,7 @@
56 Clipboard viewer |develop/clipview
62 Calendar |calendar
33 Online update * |/kolibrios/utils/osupdate
48 Process manager |cpu
48 Task manager |taskman
24 Terminal |terminal
05 Save ramdisk |rdsave
24 Shell |shell
+1 -1
View File
@@ -1,5 +1,5 @@
[rbmenu]
Processes=cpu
Task manager=taskman
Theme settings=skincfg
Background=/sys/media/palitra
System panel=syspanel
+1 -1
View File
@@ -82,7 +82,7 @@
16 Colores y Apariencia |skincfg
16 Atajos de teclado |mykey
#9 **** SENSORES
16 Procesos |cpu
16 Gestor de tareas |taskman
16 Dispositivos PCI |pcidev
16 CPUID |cpuid
16 Ghost Monitor |gmon
+1 -2
View File
@@ -23,8 +23,7 @@ Desconectar bus=kbd,37
Ajustes del sistema=setup,5
[Monitorizacion]
Procesos=cpu,60
Monitor del sistema=sysmon,57
Gestor de tareas=taskman,57
Ghost Monitor=gmon,107
Estado de red=network/netstat,33
AMDtemp=/k/utils/AMDtemp,128
+1 -1
View File
@@ -1,5 +1,5 @@
[rbmenu]
Диспетчер процессов=cpu
Диспетчер задач=taskman
Управление темой=skincfg
Настройка фона=/sys/media/palitra
Системная панель=syspanel
+1
View File
@@ -73,6 +73,7 @@
00 Файловые менеджеры > |@8
00 Спец. возможности > |@9
62 Календарь |calendar
48 Диспетчер задач |taskman
51 Виртуальные диски |tmpdisk
24 Терминал |terminal
24 Консоль SHELL |shell
+1 -2
View File
@@ -23,8 +23,7 @@ Hot Angles=HACONFIG,105
Системные настройки=setup,5
[Мониторинг]
Процессы=cpu,60
Системный монитор=sysmon,57
Диспетчер задач=taskman,57
Ghost Monitor=gmon,107
Статус сети=network/netstat,33
AMDtemp=/k/utils/AMDtemp,128
+1 -1
View File
@@ -2628,7 +2628,7 @@ modify_pce:
iglobal
cpustring db 'CPU',0
cpustring db 'TASKMAN',0
endg
uglobal
+1 -1
View File
@@ -1,5 +1,5 @@
[rbmenu]
Диспетчер процессов=cpu
Диспетчер задач=taskman
Управление темой=skincfg
Настройка фона=/sys/media/palitra
Настройка устройств=setup
+42
View File
@@ -0,0 +1,42 @@
## TASKMAN - Task Manager
Replaces CPU and SYSMON. Starts from the menu, the system panel or by
`Ctrl+Alt+Del`.
* **Processes** - threads with their CPU and memory. `Details` opens
TINFO, `End` ends the thread, `Run...` starts a program. System threads
(OS, @...) are shown with `System`.
* **Performance** - CPU, temperature, memory and network: the values on
the left, the history as a graph on the right. Temperature comes from
the CPU sensor (Intel, AMD, Hygon, VIA, Zhaoxin) or else from a board
monitoring chip (Winbond, ITE, ABIT uGuru); without either there is no
temperature graph. `CPUID` starts CPUID.
* **Disks** - partitions with label, size and, for memory disks, the
space used. `Open` shows the disk in Eolite.
* **Drivers** - the drivers the kernel has loaded. `Load...` starts
LOADDRV.
* **Autorun** - the programs of `/sys/settings/autorun.dat`. A program
turned off has `#` before it and is shown pale; `Turn on/off` adds or
removes the `#` in the file.
Lists sort by a click on a column header; a second click reverses the
order.
### Keys
| Key | Action |
|---|---|
| `Tab` | Next tab |
| `Esc` | Close |
| `Up`, `Down`, `PgUp`, `PgDn`, `Home`, `End` | Move in a list |
| `Enter` | Processes: Details; Disks: Open |
| `Del` | Processes: End |
| `Space` | Autorun: turn the program on or off |
| Right click on a row | Processes: Details; Disks: Open |
| Mouse wheel | Scroll a list |
### History
* 2026-10 - First version. Replaces CPU (processes) and SYSMON (system
monitor); adds the disks, drivers and autorun tabs and the CPU
temperature sensors; the board chips come from GMON.
+4
View File
@@ -0,0 +1,4 @@
if tup.getconfig("NO_FASM") ~= "" then return end
lang = (tup.getconfig("LANG") == "") and "en_US" or tup.getconfig("LANG")
tup.rule("taskman.asm", "fasm -dlang=" .. lang .. " %f %o " .. tup.getconfig("KPACK_CMD"), "taskman")
+423
View File
@@ -0,0 +1,423 @@
; Drawing and formatting helpers; they keep all registers unless noted.
macro __mov reg, a, b { ; mcall loads small constants shorter
if (~a eq) & (~b eq)
mpack reg, a, b
else if (~a eq) & (b eq)
movi reg, a
end if
}
; An item of a bar: a button with its color, a checkbox with its state or
; a gap
struct BAR
kind db ?
text dd ? ; the caption
arg dd ? ; -> the color, -> the state as a byte
ends
BAR_END = 0
BAR_BUTTON = 1
BAR_CHECK = 2
BAR_GAP = 3
; ebx = x shl 16 + y, ecx = color, edx -> string in UTF-8
draw_text:
pusha
or ecx, TEXT_UTF8
mcall SF_DRAW_TEXT
popa
ret
; eax -> string; out: eax = width in pixels
text_width:
push ecx esi
mov esi, eax
xor ecx, ecx
.next:
lodsb
test al, al
jz .done
call utf8_more
je .next
add ecx, 8
jmp .next
.done:
xchg eax, ecx
pop esi ecx
ret
; eax -> caption; out: eax = width of the button
button_width:
call text_width
add eax, BTN_PAD*2
ret
; Frame in the border color filled with edx. ebx = x shl 16 + w, ecx = y shl 16 + h
frame_rect:
pusha
push edx
mcall SF_DRAW_RECT, , , [sc.work_graph]
pop edx
add ebx, 1 shl 16 - 2
add ecx, 1 shl 16 - 2
mcall SF_DRAW_RECT
popa
ret
; eax = icon, ebx = x shl 16 + y, edx = the background for its white
draw_icon:
pusha
mov esi, [icons]
test esi, esi
jz .done
imul eax, ICON*ICON*4
add esi, eax
mov edi, icon_buf
mov ecx, ICON*ICON
@@:
lodsd
cmp eax, -1
jne .pixel
mov eax, edx
.pixel:
stosd
loop @b
mov edx, ebx
mcall SF_PUT_IMAGE_EXT, icon_buf, (ICON shl 16) + ICON, , 32, 0, 0
.done:
popa
ret
; eax, edx = colors; out: eax = the one half way between them, edx changed
mix:
and eax, 0xFEFEFE
and edx, 0xFEFEFE
add eax, edx
shr eax, 1
ret
; eax -> caption, edx = id, esi = color
bar_button:
pusha
mov edi, eax
call button_width
call bar_place
dec ebx ; the kernel draws one pixel more
dec ecx
mcall SF_DEFINE_BUTTON
add ebx, BTN_PAD shl 16
mov eax, [sc.work_button_text] ; then bar_text
; The end of the bar items: edi -> caption, eax = color, ebx = x shl 16,
; ecx = y shl 16 of the item
bar_text:
shr ecx, 16
add ecx, (BTN_H - TEXT_H)/2
mov bx, cx
xchg eax, ecx
mov edx, edi
call draw_text
popa
ret
; eax -> caption, edx = id, ebp = checked
bar_checkbox:
pusha
mov edi, eax
call button_width ; the box, PAD, the caption: 2 left
call bar_place
add [bar_left], 2*PAD + CHECK - 2*BTN_PAD ; then more room
or edx, BT_HIDE + BT_NOFRAME
mcall SF_DEFINE_BUTTON
mov bx, CHECK
add ecx, ((BTN_H - CHECK)/2) shl 16
mov cx, CHECK
mov [cb.left_s], ebx ; the box of box_lib, the caption
mov [cb.top_s], ecx ; as the other ones
mov eax, [sc.work_light]
mov [cb.color], eax
mov eax, [sc.work_button] ; the frame and the check
mov [cb.border_color], eax
lea eax, [ebp + ebp] ; checked
mov [cb.flags], eax
push cb
call [check_box_draw2]
add ebx, (CHECK + PAD) shl 16
sub ecx, ((BTN_H - CHECK)/2) shl 16
mov eax, [sc.work_text]
jmp bar_text
; Place in the bottom bar: from the left end, or from the right one for ids
; with bit 3. eax = width, edx = id; out: ebx = x shl 16 + w, ecx = y shl 16 + h
bar_place:
lea ebx, [eax + PAD]
test dl, 8
jnz .right
xchg ebx, [bar_left]
add [bar_left], ebx
jmp @f
.right:
sub [bar_right], ebx
mov ebx, [bar_right]
@@:
shl ebx, 16
mov bx, ax
mov ecx, [bar_y]
shl ecx, 16
mov cx, BTN_H
ret
; The items of a bar from the left, esi -> them; the buttons and the
; checkboxes get the ids from BTN_OWN on. Changes all registers.
bar_draw:
mov edx, BTN_OWN
.item:
mov bl, [esi + BAR.kind]
mov eax, [esi + BAR.text]
mov ecx, [esi + BAR.arg]
add esi, sizeof.BAR
dec bl
js .done
jz .button
dec bl
jz .check
add [bar_left], PAD ; a gap
jmp .item
.done:
ret
.button:
push esi
mov esi, [ecx]
call bar_button
pop esi
inc edx
jmp .item
.check:
movzx ebp, byte [ecx]
call bar_checkbox
inc edx
jmp .item
;-------------------------------------------------------------------------------
; Formatting: write to edi and leave it at the terminating zero.
; eax = number; printed as 8 hex digits
fmt_hex:
pusha
mov ebx, 16
mov esi, 8
jmp fmt_num
; eax = number
fmt_uint:
pusha
mov ebx, 10
xor esi, esi
fmt_num: ; ebx = base, esi = the fewest digits
xor ecx, ecx
@@:
xor edx, edx
div ebx
push edx
inc ecx
test eax, eax
jnz @b
cmp ecx, esi
jb @b
@@:
pop eax
cmp al, 10 ; 0..15 to '0'..'9', 'A'..'F'
sbb al, 0x69
das
stosb
loop @b
mov [edi], cl
mov [esp + PUSHA_EDI], edi
popa
ret
; al = a byte of UTF-8; out: ZF = 1 if it goes on with a character
utf8_more:
push eax
and al, 0xC0
cmp al, 0x80
pop eax
ret
; edx -> string; copies up to (ebx - eax) / 8 characters, TEXT_CHARS at
; most, and keeps edi
fmt_clip:
pusha
mov esi, edx
sub ebx, eax
shr ebx, 3
cmp ebx, TEXT_CHARS
jb @f
mov ebx, TEXT_CHARS
@@:
lodsb
test al, al
jz @f
call utf8_more
je .put
dec ebx
js @f
.put:
stosb
cmp edi, text_buf + TEXT_CHARS*4
jb @b
@@:
mov byte [edi], 0
popa
ret
; esi -> string
fmt_str:
push eax esi
@@:
lodsb
stosb
test al, al
jnz @b
dec edi
pop esi eax
ret
; eax -> string
fmt_unit:
xchg esi, eax
call fmt_str
xchg esi, eax
ret
; eax = KB; printed as "123 KB", "1.5 MB", "12.3 GB" etc.
fmt_size:
pusha
mov ebx, 1024
mov esi, sz_units
jmp fmt_scaled
; eax = bits a second; printed as "500 bit/s", "1.5 Mbit/s" etc.
fmt_rate:
pusha
mov ebx, 1000
mov esi, sz_bits ; then fmt_scaled
; ebx = the step of the units, esi -> the units, each ended with 0: the
; number in the largest one it fills, small ones with a decimal but .0
fmt_scaled:
xor ecx, ecx
xor edx, edx
@@:
cmp eax, ebx
jb @f
xor edx, edx
div ebx
inc ecx
jmp @b
@@:
call fmt_uint
cmp eax, 100
jae .unit
imul eax, edx, 10
xor edx, edx
div ebx
test eax, eax
jz .unit
mov byte [edi], "."
inc edi
call fmt_uint
.unit:
dec ecx
js @f
.skip:
lodsb
test al, al
jnz .skip
jmp .unit
@@:
call fmt_str
mov [esp + PUSHA_EDI], edi
popa
ret
; eax = seconds; printed as "h:mm:ss"
fmt_time:
pusha
xor edx, edx
mov ecx, 3600
div ecx
call fmt_uint
xchg eax, edx
mov cl, 60
div cl
movzx edx, ah
call .two
xchg eax, edx
call .two
mov [esp + PUSHA_EDI], edi
popa
ret
.two: ; eax = 0..99
aam
add ax, "00"
xchg al, ah
shl eax, 8
mov al, ":"
stosd
dec edi
ret
; esi -> path: the program without parameters
run_plain:
xor edx, edx ; then run_app
; esi -> path, edx -> parameters or 0
run_app:
pusha
mov [app_info.Flags], edx
mov [app_info.FileName], esi
mcall SF_FILE, app_info
popa
ret
+188
View File
@@ -0,0 +1,188 @@
; The monitoring chips of older boards, ported from GMON: Winbond W836xx and
; ITE IT87xx at ports 0x295/0x296, ABIT uGuru at 0xE0/0xE4. Their first
; temperature stands in for a CPU without a sensor.
HWM_PORT = 0x295 ; index, data at + 1
SIO_PORT = 0x2E ; Super I/O config, data at + 1
UGURU_CMD = 0xE0
UGURU_DATA = 0xE4
WB_BANK = 0x4E ; the registers of Winbond: the bank,
WB_VENDOR = 0x4F ; the vendor, 0x80 in WB_BANK: its
WB_ID = 0x5CA3 ; high byte
WB_TEMP = 0x50 ; in bank 1
SIO_CHIP_ID = 0x20 ; of the Super I/O, then of ITE
ITE_ID = 0x87 ; the high byte
ITE_TEMP = 0x29
UGURU_TEMP = 0x2100 ; bank, sensor
; The chip of the board: hwm_read; out: eax = it, 0 if none: the ports
; given back
hwm_init:
mcall SF_SET_PORTS, 0, HWM_PORT, HWM_PORT + 1
test eax, eax
jnz .uguru
call wb_probe
je .found
mcall SF_SET_PORTS, 0, SIO_PORT, SIO_PORT + 1
test eax, eax
jnz .uguru
call ite_probe
je .found
.uguru:
mcall SF_SET_PORTS, 0, UGURU_CMD, UGURU_DATA
test eax, eax
jnz .none
in al, UGURU_CMD
test al, al
jz @f
cmp al, 0xAC
jne .none
@@:
in al, UGURU_DATA
test al, al
jz @f
cmp al, 8
jne .none
@@:
mov eax, uguru_read
.found:
mov [hwm_read], eax
ret
.none:
mcall SF_SET_PORTS, 1, HWM_PORT, HWM_PORT + 1
mcall SF_SET_PORTS, 1, UGURU_CMD, UGURU_DATA
xor eax, eax
ret
; al = bank (or 0x80: the high byte of the vendor), ah = register; out: eax
wb_get:
push eax
mov ah, WB_BANK
call hwm_index
pop eax
out dx, al ; then hwm_get
; ah = register; out: eax
hwm_get:
call hwm_index
in al, dx
movzx eax, al
ret
hwm_index: ; out: dx = the data port
mov dx, HWM_PORT
mov al, ah
out dx, al
inc edx
ret
; out: ZF = 1 and eax = the read procedure if found
wb_probe:
mov ax, WB_VENDOR shl 8 ; a byte at a time
call wb_get
xchg ebx, eax
mov ax, WB_VENDOR shl 8 + 0x80
call wb_get
mov bh, al
cmp bx, WB_ID
jne .done
mov eax, wb_read
cmp eax, eax
.done:
ret
; out: ZF = 1 and eax = the read procedure if found
ite_probe:
mov eax, 0x55550187 ; MB PnP mode
mov ecx, 4
@@:
out SIO_PORT, al
shr eax, 8
loop @b
mov al, SIO_CHIP_ID
out SIO_PORT, al
in al, SIO_PORT + 1
xchg eax, esi
mov al, 2 ; leave the mode
out SIO_PORT, al
out SIO_PORT + 1, al
mcall SF_SET_PORTS, 1, SIO_PORT, SIO_PORT + 1
xchg eax, esi
cmp al, ITE_ID
mov eax, ite_read
ret
; out: eax = the first temperature
wb_read:
mov ax, WB_TEMP shl 8 + 1
jmp wb_get
ite_read:
mov ah, ITE_TEMP
jmp hwm_get
uguru_read:
mov ax, UGURU_TEMP ; then uguru_sensor
; ax = sensor; out: eax
uguru_sensor:
push ebx
mov ebx, eax
mov al, ah ; the bank
out UGURU_DATA, al
mov ah, 8
call .wait
mov al, bl
out UGURU_CMD, al
mov ah, 1
call .wait
in al, UGURU_CMD
movzx ebx, al
mov ecx, 1000 ; back to the ready state
.ready:
in al, UGURU_DATA
cmp al, 8
je .done
xor eax, eax
out UGURU_DATA, al
mov ah, 9
call .wait
loop .ready
.done:
xchg eax, ebx
pop ebx
ret
.wait: ; for ah at the data port
push ecx
mov ecx, 1000
@@:
in al, UGURU_DATA
cmp al, ah
loopne @b
pop ecx
ret
hwm_read dd nothing ; the procedure of the chip
uglobal
align 4
hwm_temp dd ? ; degrees
endg
+684
View File
@@ -0,0 +1,684 @@
; List of a tab: rows in columns with a header, a selected row and a scrollbar on
; the panel. The columns go from the left, one of them, width 0, takes what
; the others leave. A click on a row selects it, then calls the trigger of
; that button; a key of the hotkeys calls its trigger. `list` is the list of
; the open tab; a closed tab keeps it in its descriptor.
struct LIST
cols dd ? ; the columns
cols_end dd ?
sort dd ? ; the sorted column
left dd ? ; the triggers: a left click,
right dd ? ; a right click,
keys dd ? ; -> HOTKEYs, ended by 0
dim dd ? ; a byte in the row: not 0, it is pale; 0: none
count dd ?
sel dd ?
first dd ?
key dd ? ; the first dword of the selected row
desc dd ? ; 1: the sorted column goes down
view dd ? ; -> the pointers to the rows
ends
struct HOTKEY
key db ?
trigger dw ?
ends
struct COL
caption dd ?
field db ? ; offset in the row
kind db ?
width db ? ; 0: what the others leave
ends
; The list: the header, the rows and the scrollbar.
list_draw:
mov ebx, [area_w] ; what the others leave to the widest
sub ebx, 1 + SB_W
mov esi, [list.cols]
@@:
movzx edx, byte [esi + COL.width]
sub ebx, edx
add esi, sizeof.COL
cmp esi, [list.cols_end]
jb @b
mov [col_rest], ebx
mov eax, [area_h] ; the rows that fit
sub eax, 2 + HDR_H + 1
xor edx, edx
mov ecx, ROW_H
div ecx
mov [rows], eax
mov ebx, PAD shl 16 ; the header and the line under it,
mov bx, word [area_w] ; left of the scrollbar
sub bx, SB_W - 1
mov ecx, (AREA_Y shl 16) + HDR_H + 2
mov edx, [mid]
call frame_rect
xor eax, eax
mov ebp, AREA_Y + 1 + (HDR_H - TEXT_H)/2
call list_line ; then list_rows
; The rows and the scrollbar only, for new data.
list_rows:
call list_clamp
mov edi, [list.first]
mov ecx, ((AREA_Y + HDR_H + 2) shl 16) + ROW_H
mov ebp, [rows]
.row:
mov ebx, (PAD + 1) shl 16
mov bx, word [area_w]
sub bx, 1 + SB_W
mov edx, [sc.work_light]
mov esi, [sc.work_text]
cmp edi, [list.sel]
jne @f
cmp edi, [list.count] ; a row there
jae @f
mov edx, [sc.work_button]
mov esi, [sc.work_button_text]
@@:
mcall SF_DRAW_RECT
cmp edi, [list.count]
jae @f
pusha
mov eax, [list.view]
mov eax, [eax + edi*4]
mov ebp, ecx
shr ebp, 16
add ebp, (ROW_H - TEXT_H)/2
mov ecx, esi
mov esi, [list.dim] ; pale: half way to the background
test esi, esi
jz .line
cmp byte [eax + esi], 0
je .line
xchg eax, ecx
call mix
xchg eax, ecx
.line:
call list_line
popa
@@:
add ecx, ROW_H shl 16
inc edi
dec ebp
jg .row ; then sb_draw
; The scrollbar of box_lib at the right of the list, as high as it
sb_draw:
call sb_set
push sb
call [scrollbar_v_draw]
ret
; One line of the list at y = ebp: the captions if eax = 0, lines between
; them, the sorted one with an arrow, otherwise the cells of row eax in color
; ecx on background edx. Left or right as col_left says.
list_line:
pusha
mov ebx, PAD + 1 ; the left of the column
mov esi, [list.cols]
.col:
pusha
movzx edx, byte [esi + COL.field]
add edx, eax
test eax, eax
jnz .cell
mov edx, [esi + COL.caption]
mov ecx, [sc.work_text]
jmp .draw
.cell:
call cell_text
.draw:
call col_width ; the text in the cell
lea eax, [ebx + eax - CELL_PAD]
xchg eax, ebx
add eax, CELL_PAD
mov edi, text_buf
call fmt_clip
mov edx, edi
call col_left
jc @f
mov eax, edx
call text_width
neg eax
add eax, ebx
@@:
shl eax, 16
mov ax, bp
xchg eax, ebx
call draw_text
cmp dword [esp + PUSHA_EAX], 0 ; the captions
jne .picture
cmp esi, [list.cols] ; a line left of the column, but the
je @f ; first one at the frame
push ebx
mov ebx, [esp + 4 + PUSHA_EBX] ; the left
shl ebx, 16
inc ebx
mov ecx, ((AREA_Y + 1) shl 16) + HDR_H
mcall SF_DRAW_RECT, , , [sc.work_graph]
pop ebx
@@:
cmp esi, [list.sort]
jne .next
mov edi, [list.desc]
sub ebx, 5 shl 16 ; 2 pixels before the caption on the
call col_left ; right, after the one on the left
jnc @f
mov eax, text_buf
call text_width
add eax, 11
shl eax, 16
add ebx, eax
@@:
call draw_arrow
jmp .next
.picture: ; a bar or an icon in a row
movzx edx, byte [esi + COL.field]
add edx, [esp + PUSHA_EAX] ; the row
mov edx, [edx]
call col_width
cmp byte [esi + COL.kind], KIND_BAR
jb .next
ja .icon
mov ebx, [esp + PUSHA_EBX] ; the bar across the cell
add ebx, CELL_PAD
shl ebx, 16
sub eax, 2*CELL_PAD
mov bx, ax
movzx ecx, bp
shl ecx, 16
mov cx, TEXT_H
xchg eax, edx
mov edx, [sc.work_light]
call frame_rect
cmp eax, -1
je .next
add ebx, 2 shl 16 - 4 ; a light line around it, from the
add ecx, 2 shl 16 - 4 ; selected row too
movzx edx, bx
mul edx
shr eax, 10
mov bx, ax
mcall SF_DRAW_RECT, , , [sc.work_button] ; as the graphs
jmp .next
.icon:
sub eax, ICON ; in the middle of the cell
shr eax, 1
add eax, [esp + PUSHA_EBX]
shl eax, 16
lea ecx, [ebp - (ICON - TEXT_H)/2]
mov ax, cx
xchg eax, ebx
xchg eax, edx
mov edx, [esp + PUSHA_SIZE + PUSHA_EDX] ; of the first one:
; the background
call draw_icon
.next:
call col_width ; the next column after this one
add [esp + PUSHA_EBX], eax ; its left
popa
add esi, sizeof.COL
cmp esi, [list.cols_end]
jb .col
popa
ret
; esi -> column, edx -> its field in the row; out: edx -> the text of the
; cell, "" for a bar or an icon
cell_text:
cmp byte [esi + COL.kind], KIND_STR
jb .done
mov edx, [edx]
je .done
mov eax, edx
mov edi, text_buf
mov edx, edi
mov byte [edi], 0 ; -1: unknown, nothing to show
cmp eax, -1
je .done
cmp byte [esi + COL.kind], KIND_SIZE
jb .uint
ja .hex
jmp fmt_size
.hex:
cmp byte [esi + COL.kind], KIND_HEX ; a bar or an icon: drawn below
jne .done
jmp fmt_hex
.uint:
call fmt_uint
cmp byte [esi + COL.kind], KIND_PCT
jne .done
mov word [edi], "%"
.done:
ret
; esi -> column; out: CF = 1 if its caption and text go left: text and the
; widest column, but the bar
col_left:
cmp byte [esi + COL.kind], KIND_NUM ; text: CF = 1
jb .done
cmp byte [esi + COL.kind], KIND_BAR ; the bar and icons: CF = 0
jae .done
cmp byte [esi + COL.width], 1 ; the widest: CF = 1
.done:
ret
; esi -> column; out: eax = its width
col_width:
movzx eax, byte [esi + COL.width]
test eax, eax
jnz @f
mov eax, [col_rest]
@@:
ret
; The end of a scan: ebp -> the end of the view.
list_done:
sub ebp, [list.view]
shr ebp, 2
mov [list.count], ebp ; then list_sort
; Sort the view by the sorted column and find the selected row again.
list_sort:
mov ebp, [list.view]
mov ecx, 1 ; insertion sort, stable
.outer:
cmp ecx, [list.count]
jae .select
mov esi, [ebp + ecx*4]
mov ebx, ecx
.inner:
mov edi, [ebp + ebx*4 - 4]
call list_less
jnc .put
mov [ebp + ebx*4], edi
dec ebx
jnz .inner
.put:
mov [ebp + ebx*4], esi
inc ecx
jmp .outer
.select:
mov ecx, [list.count]
mov eax, [list.key]
@@:
dec ecx
js @f
mov esi, [ebp + ecx*4]
cmp [esi], eax
jne @b
mov [list.sel], ecx
@@:
ret
; esi, edi -> rows; out: CF = 1 if esi goes before edi
list_less:
pusha
mov ebx, [list.sort]
movzx ecx, byte [ebx + COL.field]
add esi, ecx
add edi, ecx
cmp [list.desc], 0
je @f
xchg esi, edi
@@:
cmp byte [ebx + COL.kind], KIND_STR
ja .num
jb @f
mov esi, [esi] ; the text by its pointer
mov edi, [edi]
@@:
lodsb ; the letters of either case alike
mov ah, [edi]
inc edi
mov dl, al
or ax, 0x2020
cmp al, ah
jne @f
test dl, dl
jz @f
cmp byte [edi - 1], 0 ; the end of edi, not a blank
jne @b
@@:
popa
ret
.num: ; -1, unknown, before 0
mov eax, [esi]
inc eax
mov edx, [edi]
inc edx
cmp eax, edx
popa
ret
; An arrow up, or down if edi = 1: a triangle of 4 lines, line i of 2*i + 1
; pixels, its tip at x = ebx shr 16, around the middle of the capitals of
; text at y = bx.
draw_arrow:
pusha
lea ecx, [edi*2 + edi + TEXT_H/2 - 2] ; from the top if it
add cx, bx ; goes up, else from the bottom
shl ecx, 16
inc ecx
shl edi, 17 ; the next line: 1 down or up
neg edi
add edi, 1 shl 16
mov bx, 1
mov esi, 4
@@:
mcall SF_DRAW_RECT, , , [sc.work_text]
add ebx, (-1 shl 16) + 2
add ecx, edi
dec esi
jnz @b
popa
ret
; eax = rows the wheel moves, esi = mouse buttons: box_lib moves the list,
; again while held; out: ebp = list.first before, drawn again if it changes
scroll_mouse:
mov ebp, [list.first]
add [list.first], eax
call sb_set
xor eax, eax
mov edi, [rows] ; all rows seen: no thumb to drag
cmp edi, [list.count]
jae @f
push sb
call [scrollbar_v_mouse]
mov eax, [sb.position]
xchg eax, [list.first]
sub eax, [list.first] ; moved while held: again after 10
jz @f ; waits of the main loop if pressed
mov eax, esi ; now, else after 2
and eax, MB_LEFT
jz @f
mov al, 2
test esi, MB_LEFT_DOWN
jz @f
mov al, 10
@@:
mov [repeat_at], eax
ret
sb_set: ; the list state to it
mov eax, [area_w]
add eax, PAD - SB_W
mov [sb.x_pos], ax
mov eax, [area_h]
mov [sb.y_size], ax
mov [sb.all_redraw], 1
mov edi, sb.max_area
mov eax, [list.count]
stosd
mov eax, [rows]
stosd
mov eax, [list.first]
stosd
mov eax, [sc.work_dark]
stosd
mov eax, [mid]
stosd
mov eax, [sc.work_graph]
stosd
ret
; Keep sel and first in range and remember the selected row.
list_clamp:
pusha
mov ecx, [list.count]
mov edi, list.sel
call clamp
jecxz @f
mov edx, [list.view]
mov eax, [edx + eax*4]
mov eax, [eax]
mov [list.key], eax
@@:
popa
pusha ; first in range
mov ecx, [list.count]
sub ecx, [rows]
inc ecx
mov edi, list.first
call clamp
popa
ret
clamp: ; [edi] into [0, ecx - 1]
mov eax, [edi]
cmp eax, ecx
jl @f
lea eax, [ecx - 1]
@@:
test eax, eax
jns @f
xor eax, eax
@@:
stosd
ret
list_key: ; al = key
mov esi, [list.keys]
.hotkey:
mov ah, [esi + HOTKEY.key]
test ah, ah
jz .move
add esi, sizeof.HOTKEY
cmp ah, al
jne .hotkey
movzx eax, [esi - sizeof.HOTKEY + HOTKEY.trigger]
jmp eax
.move:
sub al, KEY_DOWN
cmp al, KEY_PGUP - KEY_DOWN
ja .done
movzx eax, al
movsx edx, byte [.moves + eax*2 + 1]
imul edx, [rows]
movsx eax, byte [.moves + eax*2]
add edx, eax
add [list.sel], edx
call list_clamp
mov ebx, [list.sel] ; scroll to the selection
mov ecx, [rows]
sub ebx, ecx
inc ebx
sub [list.first], ebx
mov edi, list.first
call clamp
add [list.first], ebx
jmp list_rows
.done:
ret
; rows, pages for the keys KEY_DOWN..KEY_PGUP: down, up, right, home, end,
; del, pgdn, pgup
.moves db 1, 0, -1, 0, 0, 0, 0, -128, 0, 127, 0, 0, 0, 1, 0, -1
; Wheel scrolls; left button selects a row, sorts by a column or moves the
; scrollbar; right click opens the row.
list_mouse:
call get_mouse
imul eax, 3
call scroll_mouse ; every event: it follows a drag
test esi, MB_LEFT + MB_RIGHT_DOWN
jz .moved
sub ebx, PAD ; inside the list, left of the
jle .moved ; scrollbar
mov eax, [area_w]
sub eax, SB_W
cmp ebx, eax
jge .moved
sub ecx, AREA_Y + HDR_H + 2
jl .header
test esi, MB_LEFT_DOWN + MB_RIGHT_DOWN ; a row: not dragged to
jz .moved
xchg eax, ecx
xor edx, edx
mov ecx, ROW_H
div ecx
cmp eax, [rows]
jae .moved
add eax, [list.first]
cmp eax, [list.count]
jae .moved
mov [list.sel], eax
shr esi, 9 ; MB_RIGHT_DOWN: 0 left, 1 right
and esi, 1
push [list.left + esi*4] ; the selection drawn, then list_rows
jmp list_rows ; returns to the trigger
.moved: ; a drag of the thumb keeps its pixels
cmp ebp, [list.first]
jne list_rows
ret
.header:
cmp ecx, -(HDR_H + 1)
jl .moved
test esi, MB_LEFT_DOWN
jz .moved
mov esi, [list.cols] ; the column under the cursor
dec ebx
.col:
call col_width
sub ebx, eax
jl .sort
add esi, sizeof.COL
cmp esi, [list.cols_end]
jb .col
ret
.sort: ; again: the other way, else its own
xor eax, eax
cmp byte [esi + COL.kind], KIND_PCT
setae al
cmp esi, [list.sort]
jne .order
mov eax, [list.desc]
xor al, 1
.order:
mov [list.desc], eax
mov [list.sort], esi
call list_sort
jmp list_draw
; out: esi = mouse buttons held, in bits 8.. the ones pressed, not held at
; the last event, and the mouse not moved since; ebx, ecx = x, y in the
; client area; eax = the wheel
get_mouse:
mcall SF_MOUSE_GET, SSF_BUTTON_EXT
mov esi, eax
movzx eax, al
xchg al, byte [buttons]
shl eax, 8
not eax
and esi, eax
mcall SF_MOUSE_GET, SSF_WINDOW_POSITION
movsx ecx, ax ; in the client area
sar eax, 16
xchg edx, eax
mcall SF_MOUSE_GET, SSF_SCROLL_DATA
mov ebx, edx
movsx eax, ax ; the wheel
ret
no_keys db 0 ; HOTKEYs of a list without them
uglobal
align 4
list LIST
rows dd ? ; that fit the panel
col_rest dd ? ; the width of the widest column
repeat_at dd ? ; waits till a held arrow repeats
endg
+94
View File
@@ -0,0 +1,94 @@
; Strings in UTF-8; the caption starts with its encoding byte.
if lang eq ru_RU
sz_title db 3, "Диспетчер задач", 0
sz_tab_procs db "Процессы", 0
sz_tab_perf db "Нагрузка", 0
sz_tab_disks db "Диски", 0
sz_col_free db "Свободно", 0
sz_run db "Запустить...", 0
sz_kill db "Завершить", 0
sz_shutdown db "Завершение работы...", 0
sz_info db "Детали", 0
sz_system db "Системные", 0
sz_col_name db "Имя", 0
sz_col_cpu db "ЦП", 0
sz_col_mem db "Память", 0
sz_freq db "Частота", 0
sz_mhz db " МГц", 0
sz_uptime db "Время работы", 0
sz_threads db "Потоки", 0
sz_used db "Занято", 0
sz_total db "Всего", 0
sz_temp db "Температура", 0
sz_net db "Сеть", 0
sz_received db "Принято", 0
sz_sent db "Отправлено", 0
sz_crit db "Критическая", 0
sz_units db " КБ", 0, " МБ", 0, " ГБ", 0, " ТБ", 0
sz_bits db " бит/с", 0, " Кбит/с", 0, " Мбит/с", 0, " Гбит/с", 0
else if lang eq es_ES
sz_title db 3, "Gestor de tareas", 0
sz_tab_procs db "Procesos", 0
sz_tab_perf db "Recursos", 0
sz_tab_disks db "Discos", 0
sz_col_free db "Libre", 0
sz_run db "Ejecutar...", 0
sz_kill db "Finalizar", 0
sz_shutdown db "Apagar el sistema...", 0
sz_info db "Detalles", 0
sz_system db "Sistema", 0
sz_col_name db "Nombre", 0
sz_col_cpu db "CPU", 0
sz_col_mem db "Memoria", 0
sz_freq db "Frecuencia", 0
sz_uptime db "Activo", 0
sz_threads db "Hilos", 0
sz_used db "En uso", 0
sz_total db "Total", 0
sz_temp db "Temperatura", 0
sz_net db "Red", 0
sz_received db "Recibido", 0
sz_sent db "Enviado", 0
sz_crit db "Crítica", 0
else
sz_title db 3, "Task Manager", 0
sz_tab_procs db "Processes", 0
sz_tab_perf db "Performance", 0
sz_tab_disks db "Disks", 0
sz_col_free db "Free", 0
sz_run db "Run...", 0
sz_kill db "End", 0
sz_shutdown db "Shut down...", 0
sz_info db "Details", 0
sz_system db "System", 0
sz_col_name db "Name", 0
sz_col_cpu db "CPU", 0
sz_col_mem db "Memory", 0
sz_freq db "Frequency", 0
sz_uptime db "Uptime", 0
sz_threads db "Threads", 0
sz_used db "Used", 0
sz_total db "Total", 0
sz_temp db "Temperature", 0
sz_net db "Network", 0
sz_received db "Received", 0
sz_sent db "Sent", 0
sz_crit db "Critical", 0
end if
if ~ lang eq ru_RU
sz_mhz db " MHz", 0
sz_units db " KB", 0, " MB", 0, " GB", 0, " TB", 0
sz_bits db " bit/s", 0, " kbit/s", 0, " Mbit/s", 0, " Gbit/s", 0
end if
sz_col_id db "ID", 0
if lang eq ru_RU | lang eq es_ES
sz_col_num db "Nº", 0
else
sz_col_num db " #", 0
end if
sz_deg db " °C", 0
sz_pct db "%", 0
+386
View File
@@ -0,0 +1,386 @@
; Temperature on the Performance tab: the sensor of the CPU (Intel from
; Core, AMD from K8, Hygon, VIA C7, Nano and Zhaoxin; the rules are those
; of Linux coretemp, k8temp, k10temp and via-cputemp), else the first one
; of a monitoring chip of the board (hwmon.inc).
MSR_THERM_STATUS = 0x19C ; Intel: the core, the package,
MSR_PKG_THERM = 0x1B1 ; TjMax in bits 16-23
MSR_TEMP_TARGET = 0x1A2
MSR_VIA_TEMP = 0x1423 ; Nano and Zhaoxin, C7
MSR_C7_TEMP = 0x1169
AMD_NB = 0xC300 ; PCI 00:18.3, then its registers:
K8_THERMTRIP = 0xC3E4 ; K8, the others to Family 16h
NB_TEMP = 0xC3A4
VENDOR_AMD = 0x1022
VENDOR_HYGON = 0x1D94
SMN_ZEN_TEMP = 0x59800 ; the address, the index register
SMN_ZEN_INDEX = 0x60 ; on the root complex, 00:00.0
SMN_F15_TEMP = 0xD8200CA4 ; Family 15h from model 60h
SMN_F15_INDEX = 0xB8
; The sensor of the CPU, else the chip; the temperature graph if any.
sensors_init:
pusha
call cpu_sensor
cmp [cpu_temp], chip_temp
je .chip
mcall SF_THREAD_CONTROL, SSF_CREATE_THREAD, msr_probe, probe_stack_top
mov esi, 20 ; up to 0.2 s
@@:
cmp [probe], 2
je @f
mcall SF_SLEEP, 1
dec esi
jnz @b
@@:
cmp [probe], 0
jne @f
mov [cpu_temp], chip_temp ; the kernel killed the probe
@@:
cmp [tjmax], 0
jne .chip
mov byte [tjmax], 100
.chip:
cmp [cpu_temp], chip_temp ; the chip for a CPU without a sensor
jne .temp
call hwm_init
test eax, eax
jz @f
.temp:
inc [temp_on] ; a graph for any sensor
@@:
cmp [cpu_temp], intel_temp ; TjMax of Intel only
je @f
mov [temp_graph.info], no_info
@@:
popa
ret
; cpu_temp and what it reads, by the vendor and the model
cpu_sensor:
pushfd ; CPUID if the ID flag can be changed
pop eax
xor eax, 1 shl 21
push eax
popfd
pushfd
pop ecx
cmp eax, ecx
jne .done
xor eax, eax
cpuid
mov esi, eax ; the last leaf
mov edi, ebx ; vendor
mov eax, 1
cpuid
mov ebp, eax ; signature
movzx ecx, ah
and cl, 0xF ; family
movzx edx, al
shr edx, 4 ; model
cmp cl, 6
jb @f
shr eax, 12
and al, 0xF0
or dl, al
cmp cl, 0xF
jne @f
movzx eax, ah
add ecx, eax
@@:
cmp edi, "Genu"
je intel_sensor
cmp edi, " Sh" ; C7, Nano and Zhaoxin, the probe
je via_sensor ; drops the others
cmp edi, "Cent"
je via_sensor
cmp edi, "Auth"
je amd_sensor
cmp edi, "Hygo"
je amd_sensor
.done:
ret
; ecx = family, edx = model, esi = the last leaf of CPUID, ebp = signature
intel_sensor:
cmp esi, 6
jb .done
push ecx edx
mov eax, 6
cpuid
pop edx ecx
test al, 1 ; digital thermal sensor
jz .done
mov [cpu_temp], intel_temp
test al, 1 shl 6 ; the package one
jz @f
mov [therm_msr], MSR_PKG_THERM
mov [therm_valid], 1 shl 31 ; it has no "reading valid" bit
@@:
cmp ecx, 6 ; TjMax: 100 before Nehalem,
jne .done ; then from the CPU but on Atoms
cmp edx, 0x1A
jb .done
mov esi, .atoms
@@:
lodsw
test al, al
jz @f ; 0: msr_probe reads it
cmp al, dl
jne @b
@@:
mov byte [tjmax], ah
cmp dl, 0x1C ; Pineview: stepping 10
jne .done
and ebp, 0xF
cmp ebp, 10
jne .done
mov byte [tjmax], 100
.done:
ret
; TjMax of Atoms without MSR_TEMPERATURE_TARGET, and Xeon 7400
.atoms db 0x1C, 90, 0x1D, 100, 0x26, 90, 0x27, 90, 0x35, 90, 0x36, 100, 0, 0
; ecx = family, edx = model
via_sensor:
mov eax, MSR_VIA_TEMP
cmp ecx, 6
ja @f
cmp dl, 0xF
jae @f
mov ax, MSR_C7_TEMP
@@:
mov [therm_msr], eax
mov [cpu_temp], via_temp
ret
; ecx = family, edx = model
amd_sensor:
cmp ecx, 0xF
jb .done
ja .k10
push edx ; K8 with a thermal sensor
mov eax, 0x80000007
cpuid
test dl, 1
pop edx
jz .done
cmp dl, 0x69 ; revision G desktops read lower
jb @f
xchg eax, edx
mov edi, .k8_mobile
mov ecx, 3
repne scasb
je @f
mov [k8_zero], 49 - 21
@@:
mov esi, k8_temp
jmp .nb
.k10:
mov eax, SMN_ZEN_TEMP ; Zen
mov [smn_index], SMN_ZEN_INDEX
cmp ecx, 0x17
jae .smn
mov eax, SMN_F15_TEMP
mov [smn_index], SMN_F15_INDEX
cmp ecx, 0x15
jne @f
cmp edx, 0x60
jae .smn
@@:
cmp ecx, 0x16
ja .done
mov esi, amd_nb_temp
.nb:
mov ecx, AMD_NB
jmp .pci
.smn:
mov [smn_addr], eax
xor ecx, ecx
mov esi, amd_smn_temp
.pci: ; esi = the procedure, if the
call pci_read ; device is AMD or Hygon
cmp ax, VENDOR_AMD
je @f
cmp ax, VENDOR_HYGON
jne .done
@@:
mov [cpu_temp], esi
.done:
ret
.k8_mobile db 0x6C, 0x7C, 0xC1
; ecx = device shl 8 + register on bus 0; out: eax
pci_read: ; the callers keep ebx
mcall SF_PCI, SSF_READ_DWORD
ret
; out: eax = temperature of the CPU, CF = 1 if unknown
via_temp:
call read_therm
and eax, 0xFFFFFF
ret
; out: eax = the low dword of [therm_msr]
read_therm:
mcall SF_SYS_MISC, SSF_READ_MSR, , [therm_msr]
ret
intel_temp:
call read_therm
or eax, [therm_valid] ; the reading is valid
jns no_temp
shr eax, 16
and eax, 0x7F
neg eax
add eax, [tjmax]
clc
ret
k8_temp:
mov ecx, K8_THERMTRIP
call pci_read
shr eax, 16
movzx eax, al
sub eax, [k8_zero]
clc
ret
amd_smn_temp:
mcall SF_PCI, SSF_WRITE_DWORD, [smn_index], [smn_addr]
add ecx, 4 ; the data after the index
call pci_read
test eax, 1 shl 19 ; the range is -49..206
jz amd_temp
or eax, 3 shl 16
jmp amd_temp
amd_nb_temp:
mov ecx, NB_TEMP
call pci_read ; then amd_temp
; eax = the reported temperature of AMD
amd_temp:
mov edx, eax
shr eax, 24 ; 1/8 of a degree from bit 21
and edx, 3 shl 16
cmp edx, 3 shl 16
jne @f
sub eax, 49
@@:
clc
ret
chip_temp: ; none in the CPU: the first of the chip
mov eax, [hwm_temp]
jmp @b
no_temp:
stc
ret
; A thread reads the MSRs first: if one is not there, the kernel kills
; the thread, not the program.
msr_probe:
call [cpu_temp]
inc [probe]
cmp [tjmax], 0
jne @f
mcall SF_SYS_MISC, SSF_READ_MSR, , MSR_TEMP_TARGET
shr eax, 16
test al, al ; 0 in some virtual machines
jz @f
mov byte [tjmax], al
@@:
inc [probe]
mcall SF_TERMINATE_PROCESS
; Once a second: the sensors and the temperature for the graph
sensors_read:
pusha
xor eax, eax
call [hwm_read]
cmp eax, 127 ; 127 and more: no sensor
jb @f
xor eax, eax
@@:
mov [hwm_temp], eax
call [cpu_temp]
jnc .got
mov eax, [last_temp] ; not valid this time
.got:
mov [last_temp], eax
mov edi, last_temp ; not below 0
mov ecx, 1000
call clamp
mov ecx, [hist_pos]
mov [hist_temp + ecx*4], eax
popa
ret
; An ITEM of temp_info
get_tjmax:
mov eax, [tjmax]
call fmt_uint ; then deg_unit
deg_unit:
mov eax, sz_deg
jmp fmt_unit
cpu_temp dd chip_temp ; the procedure
therm_msr dd MSR_THERM_STATUS
therm_valid dd 0
tjmax dd 100
k8_zero dd 49
uglobal
align 4
temp_on dd ? ; a graph of the temperature
smn_addr dd ?
smn_index dd ?
last_temp dd ?
probe dd ? ; 1: the sensor is read, 2: done
rb 256
probe_stack_top:
hist_temp rd HIST_LEN
endg
+111
View File
@@ -0,0 +1,111 @@
; Statistics shared by the tabs, once a second: the threads, their CPU and
; memory, the history of the graphs.
struct PROC ; an item of `procs`
pid dd ?
cpu dd ? ; cycles / 256, then percent
mem dd ? ; KB
name rb 12 ; zero padded
ends
struct RAM_INFO ; function 18.20
total dd ? ; pages
free dd ?
page_faults dd ?
heap_size dd ? ; the kernel heap, bytes
heap_free dd ?
heap_blocks dd ?
heap_free_blocks dd ?
heap_max_free dd ?
heap_max_used dd ?
ends
; The threads, their CPU and memory, the history of the graphs.
sample:
pusha
mov edi, procs
xor edx, edx ; cycles of all threads / 256
xor ecx, ecx
.slot:
inc ecx
mcall SF_THREAD_INFO, pinfo
mov ebp, eax ; the last slot
cmp [pinfo.slot_state], TSTATE_FREE
je .next
mov eax, [ebx + process_information.PID]
stosd ; PROC.pid
mov eax, [ebx + process_information.cpu_usage]
shr eax, 8 ; the sum fits 32 bits
stosd ; PROC.cpu
add edx, eax
mov eax, [ebx + process_information.used_memory]
inc eax
shr eax, 10
stosd ; PROC.mem
lea esi, [ebx + process_information.process_name]
movsd ; PROC.name: 11 bytes and 0
movsd
movsd
mov byte [edi - 1], 0
cmp edi, procs + MAX_PROCS * sizeof.PROC
jae .done
.next:
cmp ecx, ebp
jb .slot
.done:
mov [procs_end], edi
; Percent of CPU = cycles of the thread / 1% of cycles of all threads.
xchg eax, edx
cdq
mov ecx, 100
div ecx
inc eax
xchg eax, ecx
mov esi, procs
@@:
mov eax, [esi + PROC.cpu]
cdq
div ecx
mov [esi + PROC.cpu], eax
add esi, sizeof.PROC
cmp esi, edi
jb @b
inc [hist_pos] ; the place of this sample
and [hist_pos], HIST_LEN - 1
mcall SF_SYSTEM, SSF_GET_RAM_INFO, ram_info
mov eax, [ram_info.total]
sub eax, [ram_info.free]
imul eax, 100
cdq
div [ram_info.total]
call sensors_read
call net_sample
mov ecx, [hist_pos]
mov [hist_mem + ecx*4], eax
mov eax, 100
sub eax, dword [procs + PROC.cpu] ; the first thread is IDLE
mov [hist_cpu + ecx*4], eax
popa
ret
uglobal
align 4
ram_info RAM_INFO
hist_pos dd ?
hist_cpu rd HIST_LEN
hist_mem rd HIST_LEN
procs_end dd ?
procs rb MAX_PROCS * sizeof.PROC
endg
+231
View File
@@ -0,0 +1,231 @@
; Autorun tab: the programs /sys/LAUNCHER starts from /sys/settings/autorun.dat.
; A line is: program parameters delay; "text" may hold spaces, # starts
; a comment. A program after # is turned off: the button or Space turns it
; on or off in the file.
struct AR
prog dd ?
params dd ?
delay dd ?
num dd ? ; of the entry
off db ? ; 1: after #, turned off
ends
; Read the file, its lines into the list.
autorun_load:
mcall SF_FILE, autorun_info ; its size; read a byte more to see
mov ecx, [autorun_bdfe.FileSizeLow] ; its end
test eax, eax
jz @f
xor ecx, ecx
@@:
inc ecx
mov [autorun_file.Count], ecx
inc ecx ; a # more, then 0
inc ecx
mcall SF_SYS_MISC, SSF_MEM_REALLOC, , [autorun_file.Buffer]
mov [autorun_file.Buffer], eax
mov [autorun_save.Buffer], eax
mov ebp, [list.view]
test eax, eax
jz list_done
mcall SF_FILE, autorun_file
cmp eax, 6 ; the end of the file: all of it
je @f
xor ebx, ebx
@@:
mov esi, [autorun_file.Buffer]
mov byte [esi + ebx], 0
add ebx, esi
mov edi, esi ; the rows: at most the bytes that
xor edx, edx ; may end a line, 0..13, and one
.count:
inc edx
@@:
cmp edi, ebx
jae @f
cmp byte [edi], 14
inc edi
jb .count
jmp @b
@@:
imul ecx, edx, 4 + sizeof.AR ; the view, then the rows
push ebx edx
mcall SF_SYS_MISC, SSF_MEM_REALLOC, , [list.view]
pop edx ebx
mov [list.view], eax
mov ebp, eax
lea edi, [eax + edx*4]
test eax, eax
jz list_done
.line:
cmp esi, ebx
jae list_done
push esi
@@:
lodsb ; find the end of the line
cmp al, 13
je @f
cmp al, 10
je @f
test al, al
jnz @b
@@:
mov byte [esi - 1], 0
xchg esi, [esp]
call get_token ; the row goes to edi, its pointer to ebp
cmp byte [eax], 0 ; empty line
je .next
cmp word [eax], "#/" ; a program turned off
je @f
cmp byte [eax], "#" ; comment
je .next
@@:
mov dl, [eax]
mov [ebp], edi
add ebp, 4
stosd ; AR.prog, params, delay
call get_token
stosd
call get_token
stosd
mov eax, ebp
sub eax, [list.view]
shr eax, 2
stosd
cmp dl, "#" ; AR.off
sete al
stosb
.next:
pop esi
jmp .line
; Put # before the selected program or take it away and save the file.
autorun_toggle:
cmp [list.count], 0 ; no rows, maybe no buffer
je .done
mcall SF_FILE, autorun_file ; the file again, as it is
cmp eax, 6 ; all of it
jne .done
mov edi, [list.key] ; AR.prog: the line in the buffer
mov ecx, [autorun_file.Buffer]
add ecx, ebx
sub ecx, edi ; not past the end: the file was cut
jbe .done
cmp byte [edi], "#"
je .on
lea esi, [edi + ecx - 1] ; one byte on from the end
lea edi, [esi + 1]
std
rep movsb
cld
mov byte [edi], "#"
inc ebx
jmp .save
.on:
lea esi, [edi + 1]
dec ecx
rep movsb
dec ebx
.save:
mov [autorun_save.Count], ebx
mcall SF_FILE, autorun_save
call autorun_load
jmp list_rows
.done:
ret
; esi -> text; out: eax -> the next word or "text", cut with zero; esi after it
get_token:
mov eax, esi
mov dh, [esi]
test dh, dh
jz .done
inc esi
cmp dh, " " ; skip blanks
jbe get_token
mov cx, " " shl 8 ; a word ends with a blank
cmp dh, '"'
jne .next
mov cx, '"' ; "text" with the quote
mov eax, esi
.next:
mov dh, [esi]
test dh, dh
jz .done
inc esi
sub dh, cl ; cl..cl + ch ends it
cmp dh, ch
ja .next
mov byte [esi - 1], 0
.done:
ret
autorun_bar:
BAR BAR_BUTTON, sz_ar_toggle, sc.work_button
db BAR_END
autorun_list LIST autorun_cols, autorun_cols_end, autorun_cols, nothing, nothing, autorun_keys, AR.off, 0, 0, 0, 0, 0, 0 ; the view on the heap
autorun_keys:
HOTKEY KEY_SPACE, autorun_toggle
db 0
autorun_cols:
COL sz_col_num, AR.num, KIND_NUM, ID_W
COL sz_col_program, AR.prog, KIND_STR, 0
COL sz_col_params, AR.params, KIND_STR, COL_W
COL sz_col_delay, AR.delay, KIND_STR, COL_W
autorun_cols_end:
if lang eq ru_RU
sz_tab_autorun db "Автозагрузка", 0
sz_col_program db "Программа", 0
sz_col_params db "Параметры", 0
sz_col_delay db "Задержка", 0
sz_ar_toggle db "Включить/выключить", 0
else if lang eq es_ES
sz_tab_autorun db "Inicio", 0
sz_col_program db "Programa", 0
sz_col_params db "Parámetros", 0
sz_col_delay db "Retardo", 0
sz_ar_toggle db "Activar/desactivar", 0
else
sz_tab_autorun db "Autorun", 0
sz_col_program db "Program", 0
sz_col_params db "Parameters", 0
sz_col_delay db "Delay", 0
sz_ar_toggle db "Turn on/off", 0
end if
autorun_info FileInfoBlock SSF_GET_INFO, 0, 0, 0, autorun_bdfe, 0, sz_autorun
autorun_file FileInfoBlock SSF_READ_FILE, 0, 0, 0, 0, 0, sz_autorun ; the buffer on
autorun_save FileInfoBlock SSF_CREATE_FILE, 0, 0, 0, 0, 0, sz_autorun ; the heap
sz_autorun db "/sys/settings/autorun.dat", 0
virtual at tab_data ; only the open tab uses it
autorun_bdfe FileInfoA
AUTORUN_DATA = $ - tab_data
end virtual
+343
View File
@@ -0,0 +1,343 @@
; Disks tab: the partitions in a sortable list, the used space as a bar
; across what the other columns leave. The kernel does not report free
; space, so for memory disks (/rd, /tmp*) the space taken by files is summed
; up. The disks are found in a thread, the tab is drawn at once.
struct DISK
num dd ? ; in the order found, the key of the row
icon dd ? ; in ICONS18, by the kind of the disk
fill dd ? ; used, 1/1024 of the size, -1: unknown
used dd ? ; KB, -1: unknown
total dd ? ; KB
name rb 16 ; the path
label rb 28
ends
MAX_DISKS = 16
WALK_MAX = 1024 ; path length
WALK_DEPTH = 16
; Start the thread that finds the disks.
disks_scan:
xor eax, eax
mov [list.count], eax
mov [list.first], eax
mov [disk_n], eax
mov [walk_stop], eax
inc [walking]
mcall SF_THREAD_CONTROL, SSF_CREATE_THREAD, walker, walk_stack_top
inc eax ; -1: no thread, nothing to wait for
jnz @f
and [walking], 0
@@:
ret
; The walker found more: the view of the disks found so far, sorted.
disks_update:
xor eax, eax
xchg eax, [walk_new]
test eax, eax
jz .done
mov esi, disks
mov ebp, disks_view
mov ecx, [disk_n]
@@:
mov [ebp], esi
add ebp, 4
add esi, sizeof.DISK
loop @b
call list_done
jmp list_rows
.done:
ret
disks_open: ; the selected disk in Eolite
cmp [list.count], 0
je .done
imul edx, [list.key], sizeof.DISK ; DISK.num
add edx, disks + DISK.name
mov esi, sz_eolite_path
jmp run_app
.done:
ret
;-------------------------------------------------------------------------------
; The thread that finds the disks and sums up the files of memory disks.
disks_find:
xor ebp, ebp ; device index in "/"
.device:
mov word [walk_path], "/"
call read_entry
jnz .done
mov edi, walk_path + 1
call fmt_str
mov ecx, edi ; end of "/device"
xor edx, edx ; partition index
.partition:
mov byte [ecx], 0
xchg ebp, edx
call read_entry
xchg ebp, edx
jnz .device
cmp [disk_n], MAX_DISKS
jae .done
mov edi, ecx
mov byte [edi], "/"
inc edi
call fmt_str
call disk_add
jmp .partition
.done:
ret
; Read entry ebp of the folder [walk_path], ebp to the next one; out:
; ZF = 1 if read, esi -> its name
read_entry:
cmp [walk_stop], 0 ; asked to stop: the thread ends
jne walker.stop
mov [fs_read.Position], ebp
inc ebp
mcall SF_FILE, fs_read
mov esi, fs_entry.FileName
test eax, eax
ret
; [walk_path] = root of the partition, edi -> its end
disk_add:
pusha
mcall SF_FILE, fs_info
test eax, eax
jnz .done
mov eax, [disk_n]
imul ebx, eax, sizeof.DISK
add ebx, disks
mov [ebx + DISK.num], eax
mov ax, word [walk_path + 1] ; the kind by the device
mov esi, disk_icons - 3
@@:
add esi, 3
cmp word [esi], 0
je @f
cmp [esi], ax
jne @b
@@:
movzx eax, byte [esi + 2]
mov [ebx + DISK.icon], eax
mov esi, walk_path
lea edi, [ebx + DISK.name]
mov ecx, DISK.label - DISK.name
call copy_cut
mov esi, fs_buf + FileInfoA.FileName ; of the partition
lea edi, [ebx + DISK.label]
mov ecx, sizeof.DISK - DISK.label
call copy_cut
mov eax, [fs_buf + FileInfoA.FileSizeLow]
mov edx, [fs_buf + FileInfoA.FileSizeHigh]
shrd eax, edx, 10
shr edx, 10 ; 4 TB and more: unknown
jz @f
or eax, -1
@@:
mov [ebx + DISK.total], eax
or dword [ebx + DISK.used], -1
or dword [ebx + DISK.fill], -1
inc [disk_n] ; listed when it is all there
mov [walk_new], ebx
test eax, eax
jz .done
mov eax, dword [walk_path + 1]
cmp ax, "rd"
je @f
and eax, 0xFFFFFF
cmp eax, "tmp"
jne .done
@@:
xor ecx, ecx
xor edx, edx
mov edi, [esp + PUSHA_EDI] ; the end of the path
call disk_walk
cmp ecx, [ebx + DISK.total] ; not more used than there is
jbe @f
mov ecx, [ebx + DISK.total]
@@:
mov [ebx + DISK.used], ecx
xchg eax, ecx
mov edx, 1024
mul edx
div dword [ebx + DISK.total]
mov [ebx + DISK.fill], eax
mov [walk_new], ebx
.done:
popa
ret
; esi -> text, edi -> a field of ecx bytes: the text, cut to fit it, not in
; the middle of a character
copy_cut:
rep movsb
@@:
dec edi
mov al, [edi]
and al, 0xC0
cmp al, 0x80
je @b
mov [edi], cl
ret
; The thread.
walker:
call disks_find
.stop:
and [walking], 0
mcall SF_TERMINATE_PROCESS
; Ask the walker to stop and wait till it is gone.
stop_walker:
mov [walk_stop], 1
@@:
and [walk_new], 0
cmp [walking], 0
je @f
mcall SF_SLEEP, 1
jmp @b
@@:
ret
; Add the size of files under [walk_path] to ecx, KB; edi -> end of the path,
; edx = depth
disk_walk:
pusha
xor ebp, ebp ; index in the folder
inc edx
.next:
call read_entry
jnz .done
test byte [fs_entry.Attributes], FA_LABEL
jnz .next
test byte [fs_entry.Attributes], FA_FOLDER
jnz .folder
mov eax, [fs_entry.FileSizeLow]
add eax, 1023
shr eax, 10
add ecx, eax
jmp .next
.folder:
cmp byte [esi], "." ; skip "." and ".."
jne @f
cmp byte [esi + 1], 0
je .next
cmp word [esi + 1], "."
je .next
@@:
cmp edx, WALK_DEPTH
jae .next
lea eax, [edi + 264]
cmp eax, walk_path + WALK_MAX
jae .next
push edi
mov byte [edi], "/"
inc edi
call fmt_str
call disk_walk
pop edi
mov byte [edi], 0
jmp .next
.done:
mov [esp + PUSHA_ECX], ecx
popa
ret
disks_bar:
BAR BAR_BUTTON, sz_open, sc.work_button
db BAR_END
disks_list LIST disks_cols, disks_cols_end, disks_cols + sizeof.COL, nothing, disks_open, disks_keys, 0, 0, 0, 0, 0, 0, tab_data
disks_keys:
HOTKEY KEY_ENTER, disks_open
db 0
disks_cols:
COL sz_col_num, DISK.icon, KIND_ICON, ID_W
COL sz_col_name, DISK.name, KIND_TEXT, COL_W
COL sz_col_label, DISK.label, KIND_TEXT, COL_W
COL sz_pct, DISK.fill, KIND_BAR, 0
COL sz_used, DISK.used, KIND_SIZE, COL_W
COL sz_col_size, DISK.total, KIND_SIZE, COL_W
disks_cols_end:
if lang eq ru_RU
sz_col_size db "Размер", 0
sz_col_label db "Метка", 0
sz_open db "Открыть", 0
else if lang eq es_ES
sz_col_size db "Tamaño", 0
sz_col_label db "Etiqueta", 0
sz_open db "Abrir", 0
else
sz_col_size db "Size", 0
sz_col_label db "Label", 0
sz_open db "Open", 0
end if
sz_eolite_path db "/sys/File Managers/EOLITE", 0
; the first two letters of the device, the icon; the last one for the others
disk_icons db "rd", 58, "tm", 51, "fd", 5, "cd", 19, "us", 57, 0, 0, 50
fs_read FileInfoBlock SSF_READ_FOLDER, 0, 1, 1, fs_buf, 0, walk_path ; cp866
; names, one entry from Position on
fs_info FileInfoBlock SSF_GET_INFO, 0, 3, 0, fs_buf, 0, walk_path ; UTF-8
; volume label
uglobal
disk_n dd ? ; the disks the walker found
walking dd ?
walk_stop dd ?
walk_new dd ?
rb 1024
walk_stack_top:
endg
virtual at tab_data ; only the open tab uses it
disks_view rd MAX_DISKS
disks rb MAX_DISKS * sizeof.DISK
fs_buf FileInfoHeader ; then an entry of a folder; a
fs_entry FileInfoA ; partition from fs_buf on
walk_path rb WALK_MAX
DISKS_DATA = $ - tab_data
end virtual
+92
View File
@@ -0,0 +1,92 @@
; Drivers tab: the drivers loaded by the kernel (function 68.31).
struct DRV
num dd ? ; in the list, the key of the row
name rb 16 ; from here on the item of the kernel
next dd ?
handle dd ? ; the kernel keeps the previous item here
base dd ?
start dd ? ; the entry of the driver
service dd ?
ends
MAX_DRIVERS = 64
; The drivers the kernel has now.
drivers_scan:
mcall SF_SYS_MISC, SSF_GET_DRIVER_DATA, 1
mov esi, ecx ; the last driver
mov edx, ebx ; the first one
mov ebp, drivers_view
mov edi, drivers + DRV.name
.next:
cmp ebp, drivers_view + MAX_DRIVERS*4
jae list_done
mcall SF_SYS_MISC, SSF_GET_DRIVER_DATA, 2
test eax, eax
jnz list_done
lea eax, [edi - DRV.name]
mov [ebp], eax
add ebp, 4
lea eax, [ebp - drivers_view]
shr eax, 2
mov dword [edi + DRV.num - DRV.name], eax
mov eax, dword [edi + DRV.next - DRV.name]
mov dword [edi + DRV.handle - DRV.name], edx
add edi, sizeof.DRV
cmp edx, esi
mov edx, eax
jne .next
jmp list_done
drivers_load: ; RUN with the name of the driver to type
mov esi, sz_run_path
mov edx, sz_loaddrv
jmp run_app
drivers_bar:
BAR BAR_BUTTON, sz_load, sc.work_button
db BAR_END
drivers_list LIST drivers_cols, drivers_cols_end, drivers_cols, nothing, nothing, no_keys, 0, 0, 0, 0, 0, 0, tab_data
drivers_cols:
COL sz_col_num, DRV.num, KIND_NUM, ID_W
COL sz_col_name, DRV.name, KIND_TEXT, 0
COL sz_col_handle, DRV.handle, KIND_HEX, COL_W
COL sz_col_base, DRV.base, KIND_HEX, COL_W
COL sz_col_service, DRV.service, KIND_HEX, COL_W
drivers_cols_end:
if lang eq ru_RU
sz_tab_drivers db "Драйверы", 0
sz_col_handle db "Дескриптор", 0
sz_col_base db "База", 0
sz_col_service db "Сервис", 0
sz_load db "Загрузить...", 0
else if lang eq es_ES
sz_tab_drivers db "Controladores", 0
sz_col_handle db "Manejador", 0
sz_col_base db "Base", 0
sz_col_service db "Servicio", 0
sz_load db "Cargar...", 0
else
sz_tab_drivers db "Drivers", 0
sz_col_handle db "Handle", 0
sz_col_base db "Base", 0
sz_col_service db "Service", 0
sz_load db "Load...", 0
end if
sz_loaddrv db "/sys/LOADDRV ", 0
virtual at tab_data ; only the open tab uses it
drivers_view rd MAX_DRIVERS
drivers rb MAX_DRIVERS * sizeof.DRV
DRIVERS_DATA = $ - tab_data
end virtual
+532
View File
@@ -0,0 +1,532 @@
; Performance tab: CPU, temperature when there is a sensor, memory and
; network history in rows, lines between them. A row: the icon, the title
; and the items on the left, the graph on the right.
GRAPH_STEP = 4 ; pixels per sample
INFO_W = 256 + 2*PAD + ICON ; the icon, the title, the items, PAD
NET_DEVICES = 16 ; of the kernel
struct G ; a graph
title dd ?
hist dd ? ; dwords up to the top
hist2 dd ? ; 0, the network: received, sent
info dd ? ; items left of the graph
unit dd ? ; of the value in the title
top dd ? ; -> the top of the scale
on dd ? ; -> not 0 if shown
icon dd ? ; before the title
ends
struct ITEM ; a line left of a graph
text dd ?
get dd ? ; edi -> the text; out: edi after it
ends
struct NET_BYTES ; of all the devices
rx dq ?
tx dq ?
ends
perf_draw: ; eax = TAB.draw: with the frames,
lea esi, [eax - TAB.update] ; TAB.update: esi = 0, without
mov edi, shown ; the graphs there is data for
mov eax, graphs
.shown:
mov edx, [eax + G.on]
cmp dword [edx], 0
je @f
stosd
@@:
add eax, sizeof.G
cmp eax, graphs_end
jb .shown
sub edi, shown
shr edi, 2
xchg edi, [shown_n]
cmp edi, [shown_n] ; one came or went: all again
je .draw
test esi, esi
jz draw_window
.draw:
xor ebp, ebp
.graph:
call graph_frame
call perf_graph
inc ebp
cmp ebp, [shown_n]
jb .graph
ret
; The button of the bar.
perf_cpuid:
mov esi, sz_cpuid_path
jmp run_plain
; ebp = graph; out: ebx = x shl 16 + w, ecx = y shl 16 + h of its frame.
; Between the rows a line, PAD from both.
graph_frame:
mov eax, [area_h]
dec eax
xor edx, edx
div [shown_n] ; from a row to the next one
mov ecx, ebp
imul ecx, eax
add ecx, AREA_Y + 1 + PAD
shl ecx, 16
sub eax, 2*PAD + 1
mov cx, ax
mov ebx, (3*PAD + 1 + INFO_W) shl 16
mov bx, word [area_w]
sub bx, 2 + 3*PAD + INFO_W
ret
; ecx = y shl 16 of a frame: the line between its row and the one above
row_line:
pusha
shr ecx, 16
sub ecx, PAD + 1 ; the middle of the gap above
shl ecx, 16
inc ecx
mov ebx, (PAD + 1) shl 16
mov bx, word [area_w]
sub bx, 2
mcall SF_DRAW_RECT, , , [sc.work_graph]
popa
ret
; ebp = graph, ebx and ecx = its frame, esi = 0: no frame
perf_graph:
pusha
test esi, esi
jz .title
mov edx, [sc.work_light]
call frame_rect
call row_line ; the first one on the panel border
.title:
mov ebp, [shown + ebp*4]
mov esi, [ebp + G.hist]
mov edx, [ebp + G.hist2]
mov edi, [hist_pos] ; the last value
mov eax, [esi + edi*4]
test edx, edx
jz @f
add eax, [edx + edi*4] ; the network: both ways
mov edi, text_buf
call fmt_rate
jmp .titled
@@:
mov edi, text_buf
call fmt_uint
mov eax, [ebp + G.unit]
call fmt_unit
.titled:
call info_lines ; the lines left of it
mov eax, [ebp + G.top] ; the top: 100 %, TjMax, the network:
mov eax, [eax] ; the largest rate of the columns
add ebx, 1 shl 16 - 2 ; bars inside the frame, newest on the right
add ecx, 1 shl 16 - 2
movzx edi, bx
test edx, edx
jz .scaled
call net_scale
.scaled:
mov [scale], eax
mov ebp, [hist_pos]
.bar: ; the network: received on the left,
mov eax, GRAPH_STEP ; sent on the right, lighter
cmp edi, eax
jae @f
mov eax, edi
@@:
mov bx, ax
sub edi, eax
pusha
shl edi, 16
add ebx, edi
mov edi, [sc.work_button]
test edx, edx
jz .last
mov eax, ebx
shr ax, 1
sub bx, ax
call .value
shl ebx, 16
add eax, ebx
xchg eax, ebx
mov esi, edx
mov eax, [sc.work_light] ; sent: half way to the background
mov edx, edi
call mix
xchg eax, edi
.last:
call .value
popa
dec ebp
and ebp, HIST_LEN - 1
test edi, edi
jnz .bar
test edx, edx ; the network: its top at the top right
jz .critical
mov edi, text_buf
mov eax, [scale]
call fmt_rate
mov ebx, [area_w]
shl ebx, 16
mov bx, [esp + PUSHA_ECX + 2] ; y of the frame
add ebx, ((-6 - INFO_W + ICON + PAD) shl 16) + 4
call info_value
@@:
popa
ret
.critical: ; the temperature: a line 10 below
cmp esi, hist_temp ; the top
jne @b
movzx eax, cx
imul eax, 10
div [scale] ; edx = G.hist2 = 0 here
shl eax, 16
add ecx, eax
mov cx, 1
mov ebx, [esp + PUSHA_EBX] ; the frame
add ebx, 1 shl 16 - 2
mcall SF_DRAW_RECT, , , [red]
jmp @b
; esi + ebp*4 -> value, edi = color: its bar at the bottom, the background
; above it, not one over the other, so it does not flicker
.value:
pusha
mov eax, [esi + ebp*4]
cmp eax, [scale] ; not over the top
jb @f
mov eax, [scale]
@@:
movzx esi, cx
mul esi
div [scale]
xchg ebp, eax
sub cx, bp
mcall SF_DRAW_RECT, , , [sc.work_light]
movzx edx, cx
shl edx, 16
add ecx, edx
mov cx, bp
mcall SF_DRAW_RECT, , , edi
popa
ret
; esi, edx -> the history received and sent, edi = the width of the graph;
; out: eax = its top, the largest rate shown up to 1, 2, 5, 10, 20, 50...
; bit/s while it fits
net_scale:
push edi
mov ebp, [hist_pos]
xor eax, eax
.max:
cmp eax, [esi + ebp*4]
jae @f
mov eax, [esi + ebp*4]
@@:
cmp eax, [edx + ebp*4]
jae @f
mov eax, [edx + ebp*4]
@@:
dec ebp
and ebp, HIST_LEN - 1
sub edi, GRAPH_STEP
jg .max
pop edi
cmp eax, 2000000000
ja .done
xor ebp, ebp
inc ebp
@@:
cmp ebp, eax
jae @f
add ebp, ebp
cmp ebp, eax
jae @f
lea ebp, [ebp*4 + ebp]
shr ebp, 1
cmp ebp, eax
jae @f
add ebp, ebp
jmp @b
@@:
xchg eax, ebp
.done:
ret
; text_buf on the right of an item line at ebx = x shl 16 + y
info_value:
pusha
mov ecx, [sc.work_text]
mov edx, text_buf
mov eax, edx
call text_width
neg eax
add eax, INFO_W - ICON - PAD
shl eax, 16
add ebx, eax
call draw_text
popa
ret
; ebp -> graph, ecx = y shl 16 + h of its frame, text_buf = its value:
; the title and the items a line each as fit, the label on the left, the
; value on the right. The ITEMs end with 0.
info_lines:
pusha
movzx esi, cx ; the height left
mov ebx, ((2*PAD + 1) shl 16) + INFO_W
mcall SF_DRAW_RECT, , , [sc.work_light]
mov ebx, ecx ; the icon, the lines after it
shr ebx, 16
add ebx, (2*PAD + 1) shl 16 - 1
mov eax, [ebp + G.icon]
mov edx, [sc.work_light]
call draw_icon
add ebx, ((ICON + PAD) shl 16) + 1
mov edx, [ebp + G.title]
mov ebp, [ebp + G.info]
mov ecx, [sc.work_text]
jmp .line
.item:
mov edx, [ebp + ITEM.text]
test edx, edx
jz .done
mov edi, text_buf
pusha
call [ebp + ITEM.get]
popa
add ebp, sizeof.ITEM
.line:
sub esi, 16
jb .done
call draw_text
mov eax, edx ; the value in the rest of the line
call text_width
pusha
mov ebx, INFO_W - 8 - ICON - PAD
mov edx, text_buf
mov edi, edx
call fmt_clip
popa
call info_value
add ebx, 16
jmp .item
.done:
popa
ret
; Once a second: the bytes of the network devices, but the loopback.
net_sample:
pusha
mov edi, net_sum
xor eax, eax
mov ecx, (net_last - net_sum) / 4 ; and net_up
rep stosd
mov ebx, (NET_DEVICES - 1) shl 8
.device:
push ebx ; bl = SSF_DEVICE_TYPE
mcall SF_NETWORK_GET
test eax, eax ; -1: none, 0: the loopback
jle .next
inc [net_up]
mov bl, SSF_RX_BYTE_COUNT
mcall SF_NETWORK_GET
add dword [net_sum.rx], eax
adc dword [net_sum.rx + 4], ebx
mov ebx, [esp]
mov bl, SSF_TX_BYTE_COUNT
mcall SF_NETWORK_GET
add dword [net_sum.tx], eax
adc dword [net_sum.tx + 4], ebx
.next:
pop ebx
dec bh
jns .device
mov ecx, [hist_pos]
mov esi, net_sum.rx
mov ebx, hist_rx
call .rate
mov ebx, hist_tx
call .rate
or [net_primed], -1
popa
ret
.rate: ; since the last second, 0 at first
mov eax, [esi]
mov edx, [esi + 4]
sub eax, [edi]
sbb edx, [edi + 4]
movsd ; the sum is the last one now
movsd
jae @f
xor eax, eax ; a device went away
@@:
shl eax, 3 ; bits
and eax, [net_primed]
mov [ebx + ecx*4], eax
ret
; The items of the lines left of the graphs: edi -> the text; out:
; edi after it.
get_freq:
mcall SF_SYSTEM, SSF_GET_CPU_FREQUENCY
mov ecx, 1000000
call fmt_quot
mov eax, sz_mhz
jmp fmt_unit
get_uptime:
mcall SF_SYSTEM_GET, SSF_TIME_COUNT
xor edx, edx
mov ecx, 100
div ecx
jmp fmt_time
get_threads:
mov eax, [procs_end]
sub eax, procs
mov ecx, sizeof.PROC ; then fmt_quot
; eax / ecx, edx = the remainder
fmt_quot:
xor edx, edx
div ecx
jmp fmt_uint
get_used:
mov eax, [ram_info.total]
sub eax, [ram_info.free]
jmp @f
get_free:
mov eax, [ram_info.free]
jmp @f
get_total:
mov eax, [ram_info.total]
@@:
shl eax, 2 ; pages to KB
jmp fmt_size
get_rx:
mov esi, net_sum.rx
mov ebx, hist_rx
jmp @f
get_tx:
mov esi, net_sum.tx
mov ebx, hist_tx
@@: ; the rate, then the total
mov eax, [hist_pos]
mov eax, [ebx + eax*4]
call fmt_rate
mov word [edi], " ("
scasw
mov eax, [esi]
mov edx, [esi + 4]
shrd eax, edx, 10
call fmt_size
mov word [edi], ")"
inc edi
ret
graphs:
G sz_col_cpu, hist_cpu, 0, cpu_info, sz_pct, pct_top, pct_top, 48
temp_graph G sz_temp, hist_temp, 0, temp_info, sz_deg, tjmax, temp_on, 68
G sz_col_mem, hist_mem, 0, mem_info, sz_pct, pct_top, pct_top, 51
G sz_net, hist_rx, hist_tx, net_info, 0, pct_top, net_up, 12
graphs_end:
pct_top dd 100
perf_bar:
BAR BAR_BUTTON, sz_cpuid_path + 5, sc.work_button ; "CPUID"
db BAR_END
sz_cpuid_path db "/sys/CPUID", 0
cpu_info ITEM sz_freq, get_freq
ITEM sz_uptime, get_uptime
ITEM sz_threads, get_threads
dd 0
mem_info ITEM sz_used, get_used
ITEM sz_col_free, get_free
ITEM sz_total, get_total
dd 0
net_info ITEM sz_received, get_rx
ITEM sz_sent, get_tx
dd 0
temp_info ITEM sz_crit, get_tjmax ; Intel
no_info dd 0
uglobal
align 4
shown rd 4 ; -> graphs
shown_n dd ?
net_primed dd ?
scale dd ? ; of the bars being drawn
net_sum NET_BYTES
net_up dd ? ; the devices, but the loopback
net_last NET_BYTES
hist_rx rd HIST_LEN ; bits a second
hist_tx rd HIST_LEN
endg
+98
View File
@@ -0,0 +1,98 @@
; Processes tab: the threads in a sortable list.
; The threads to show, then the whole list or the rows only.
procs_draw:
call procs_filter
jmp list_draw
procs_update:
call procs_filter
jmp list_rows
; The threads to show, without the system ones unless asked.
procs_filter:
mov esi, procs
mov ebp, procs_view
.next:
cmp esi, [procs_end]
jae list_done
cmp [show_system], 0
jne .add
cmp esi, procs ; IDLE
je .skip
cmp byte [esi + PROC.name], "@"
je .skip
cmp dword [esi + PROC.name], "OS"
je .skip
.add:
mov [ebp], esi
add ebp, 4
.skip:
add esi, sizeof.PROC
jmp .next
procs_button: ; edx = button id
jmp [.btns + (edx - BTN_OWN)*4]
.btns dd .system, procs_info, procs_kill, procs_run ; as in procs_bar
.system:
xor [show_system], 1
jmp draw_window
; The buttons: Run..., End, Details.
procs_run:
mov esi, sz_run_path
jmp run_plain
procs_kill: ; the key of a row is its PID
mcall SF_SYSTEM, SSF_TERMINATE_THREAD_ID, [list.key]
ret
procs_info:
mcall SF_SYSTEM, SSF_GET_THREAD_SLOT, [list.key]
test eax, eax
jz .done
mov edi, text_buf
call fmt_uint
mov esi, sz_tinfo_path
mov edx, text_buf
jmp run_app
.done:
ret
procs_bar:
BAR BAR_CHECK, sz_system, show_system
BAR BAR_BUTTON, sz_info, sc.work_button
BAR BAR_BUTTON, sz_kill, red
BAR BAR_GAP, 0, 0 ; away from End
BAR BAR_BUTTON, sz_run, green
db BAR_END
procs_list LIST procs_cols, procs_cols_end, procs_cols, nothing, procs_info, procs_keys, 0, 0, 0, 0, 0, 0, tab_data
procs_keys:
HOTKEY KEY_ENTER, procs_info
HOTKEY KEY_DEL, procs_kill
db 0
procs_cols:
COL sz_col_id, PROC.pid, KIND_NUM, ID_W
COL sz_col_name, PROC.name, KIND_TEXT, 0
COL sz_col_cpu, PROC.cpu, KIND_PCT, COL_W
COL sz_col_mem, PROC.mem, KIND_SIZE, COL_W
procs_cols_end:
uglobal
show_system db ?
endg
virtual at tab_data ; only the open tab uses it
procs_view rd MAX_PROCS
PROCS_DATA = $ - tab_data
end virtual
+344
View File
@@ -0,0 +1,344 @@
; SPDX-License-Identifier: GPL-2.0-only
;
; Task manager. A tab is a row of the `tabs` table: its caption, list
; and handlers. To add a tab, add a row and an .inc file with the handlers.
include "../../KOSfuncs.inc"
include "../../macros.inc"
include "../../develop/libraries/box_lib/box_lib.mac"
include "../../develop/libraries/libs-dev/libio/libio.inc"
format meos 01
entry start
include "gui.inc"
include "hwmon.inc"
include "list.inc"
include "locale.inc"
include "sensors.inc"
include "stats.inc"
include "window.inc"
include "tabs/autorun.inc"
include "tabs/disks.inc"
include "tabs/drivers.inc"
include "tabs/perf.inc"
include "tabs/procs.inc"
;-------------------------------------------------------------------------------
start:
mcall SF_SET_EVENTS_MASK, EVENTS
mcall SF_SYS_MISC, SSF_LOAD_DLL, box_lib_path
test eax, eax
jz exit
xchg ecx, eax
mov ebp, box_lib ; the names become the procs
.import:
mov ebx, ecx
.export:
mov esi, [ebx]
test esi, esi
jz exit
add ebx, 8
mov edi, [ebp]
@@:
lodsb
scasb
jne .export
test al, al
jnz @b
mov edx, [ebx - 4]
mov [ebp], edx
add ebp, 4
cmp dword [ebp], 0
jne .import
mcall SF_SYS_MISC, SSF_HEAP_INIT
mcall SF_SYS_MISC, SSF_MEM_OPEN, icons_name, 0, 0 ; of @RESHARE
mov [icons], eax
call sensors_init
reopen:
call open_tab
redraw:
call draw_window
still:
mcall SF_SYSTEM_GET, SSF_TIME_COUNT
mov ebx, [next_tick]
sub ebx, eax
jg .wait
add eax, TICK
mov [next_tick], eax
call sample
mcall SF_THREAD_INFO, pinfo, -1
test [pinfo.wnd_state], WND_MINIMIZED + WND_ROLLED_UP
jnz still
mov eax, TAB.update
call tab_call
jmp still
.wait:
cmp [repeat_at], 0 ; an arrow held: the mouse again soon
je @f
mov ebx, 4
@@:
mcall SF_WAIT_EVENT_TIMEOUT
dec eax ; EV_REDRAW
jz redraw
dec eax ; EV_KEY
jz key
dec eax ; EV_BUTTON
jz button
cmp al, EV_MOUSE - EV_BUTTON ; the mouse, or the time with
je .mouse ; it held
cmp al, EV_IDLE - EV_BUTTON
jne still
cmp [repeat_at], 0 ; a held arrow when it is time
je still
dec [repeat_at]
jnz still
.mouse:
mov eax, TAB.mouse
call tab_call
jmp still
key:
mcall SF_GET_KEY
shr eax, 8
cmp al, KEY_ESC
je exit
cmp al, KEY_TAB ; the next tab
je next_tab
call tab_list ; other keys are for lists
jz still
call list_key
jmp still
button:
mcall SF_GET_BUTTON
shr eax, 8
cmp eax, 1
je exit
cmp eax, BTN_OWN
jae .own
sub eax, BTN_TAB
cmp eax, BTN_SHUTDOWN - BTN_TAB
jb switch_tab
mov esi, sz_end_path
call run_plain
jmp still
.own:
xchg eax, edx
mov eax, TAB.button
call tab_call
jmp still
next_tab:
mov eax, [cur_tab]
inc eax
cmp eax, NTABS
jb switch_tab
xor eax, eax ; then switch_tab
switch_tab: ; eax = tab
cmp eax, [cur_tab] ; the open one: nothing to do
je still
push eax
call tab_list ; the old tab keeps its list
mov esi, list
call copy_list
pop [cur_tab]
jmp reopen
exit:
call stop_walker
mcall SF_TERMINATE_PROCESS
; Open the current tab: its list, then its activate handler.
open_tab:
and [repeat_at], 0
call stop_walker
call tab_list
mov esi, edi
mov edi, list
call copy_list
mov eax, TAB.activate
tab_call: ; eax = handler in TAB
imul ecx, [cur_tab], sizeof.TAB
movzx ecx, word [tabs + ecx + eax]
jmp ecx
nothing:
ret
; out: edi -> list of the current tab or 0, ZF = 1 if 0
tab_list:
imul edi, [cur_tab], sizeof.TAB
movzx edi, word [tabs + edi + TAB.list]
test edi, edi
ret
; Copy the list at esi to edi unless ZF = 1: the tab has none.
copy_list:
jz @f
mov ecx, sizeof.LIST / 4
rep movsd
@@:
ret
;-------------------------------------------------------------------------------
; Settings
MIN_W = 640 ; fits the longest bottom bar (ru_RU)
MIN_H = 400 ; four graphs are still readable
TICK = 100 ; statistics period, 1/100 s
HIST_LEN = 1024 ; power of 2, the bars of a 4K wide window
MAX_PROCS = 256
; Layout
PAD = 8 ; margins and gaps
TOP = 12 ; above the tabs
TAB_H = 24
AREA_Y = TOP + TAB_H - 1 ; top of the panel, the bottom of the tabs
BTN_H = 24
BTN_PAD = 12 ; text to the sides of a button
CHECK = 14 ; checkbox
ICON = 18 ; icons of @RESHARE
TEXT_CHARS = 63 ; the longest text drawn
TEXT_H = 14 ; 8x16 glyphs look centered as 14 lines
; The window and the text
EVENTS = EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_MOUSE + EVM_MOUSE_FILTER
WIN_STYLE = 0x73000000 ; skinned, a caption, coordinates in
; the client area, not filled: drawn
TEXT_UTF8 = 0xB0000000 ; asciiz, UTF-8, 8x16
WND_MAXIMIZED = 1 ; process_information.wnd_state
WND_MINIMIZED = 2
WND_ROLLED_UP = 4
; Lists
COL_W = 112
ID_W = 3*8 + 2*CELL_PAD ; a number: ID, Nº or #, the arrow
KIND_TEXT = 0 ; zero ended text in the row, sorted ascending
KIND_STR = 1 ; pointer to text
KIND_NUM = 2
KIND_PCT = 3 ; from here on sorted down at first
KIND_SIZE = 4
KIND_HEX = 5
KIND_BAR = 6 ; 1/1024 of the cell filled
KIND_ICON = 7 ; in ICONS18
HDR_H = 24 - 2 ; 24 with its lines, as an arrow
ROW_H = 20
SB_W = 24 ; scrollbar, as high as the list
CELL_PAD = 8
; Keys and mouse buttons
KEY_TAB = 9
KEY_ENTER = 13
KEY_SPACE = 32
KEY_ESC = 27
KEY_DOWN = 177 ; the moves in the lists up to
KEY_DEL = 182
KEY_PGUP = 184 ; here
MB_LEFT = 1 ; held
MB_LEFT_DOWN = 0x100 ; pressed, not held at the last event
MB_RIGHT_DOWN = 0x200
; pusha: where it keeps the registers
PUSHA_EDI = 0
PUSHA_EBX = 16
PUSHA_EDX = 20
PUSHA_ECX = 24
PUSHA_EAX = 28
PUSHA_SIZE = 32
; Buttons
BTN_TAB = 2
BTN_SHUTDOWN = 8 ; ids with bit 3 go to the right
BTN_OWN = 16 ; ids from here on belong to the tab
struct TAB ; a row of `tabs`
caption dw ?
list dw ? ; LIST or 0
activate dw ? ; the tab is opened
draw dw ? ; full redraw of the panel
update dw ? ; new statistics
button dw ? ; edx = button id
mouse dw ?
bar dw ? ; the items of its bottom bar
ends
;-------------------------------------------------------------------------------
tabs:
TAB sz_tab_procs, procs_list, nothing, procs_draw, procs_update, procs_button, list_mouse, procs_bar
TAB sz_tab_perf, 0, nothing, perf_draw, perf_draw, perf_cpuid, get_mouse, perf_bar
TAB sz_tab_disks, disks_list, disks_scan, list_draw, disks_update, disks_open, list_mouse, disks_bar
TAB sz_tab_drivers, drivers_list, drivers_scan, list_draw, nothing, drivers_load, list_mouse, drivers_bar
TAB sz_tab_autorun, autorun_list, autorun_load, list_draw, nothing, autorun_toggle, list_mouse, autorun_bar
NTABS = ($ - tabs) / sizeof.TAB
app_info FileInfoBlock SSF_START_APP, 0, 0, 0, 0, 0, 0 ; the parameters, the path
sz_run_path db "/sys/RUN", 0
sz_end_path db "/sys/END", 0
sz_tinfo_path db "/sys/TINFO", 0
icons_name db "ICONS18", 0
box_lib_path db "/sys/lib/box_lib.obj", 0
align 4
box_lib:
import box_lib, \
scrollbar_v_draw, "scrollbar_v_draw", \
scrollbar_v_mouse, "scrollbar_v_mouse", \
check_box_draw2, "check_box_draw2"
sb scrollbar SB_W - 1, 0, 0, AREA_Y, SB_W - 1, 0, 0, 0, 0, 0, 0, 1 ; the sizes - 1:
; box_lib draws a pixel more
cb check_box2 0, 0, PAD, 0, 0, 0x80000000, cb.size_of_str, 0 ; no text: its length
IncludeUGlobals
align 4
sc system_colors ; the button color: the main one
green dd ? ; of the button: run
red dd ? ; and of high values, end
mid dd ? ; the list header, the scrollbar
pinfo process_information
next_tick dd ?
cur_tab dd ?
buttons dd ? ; mouse buttons held at the last event
area_w dd ? ; panel: x = PAD, y = AREA_Y
area_h dd ?
bar_y dd ? ; bottom bar
bar_left dd ?
bar_right dd ? ; left end of the right buttons
icons dd ? ; ICONS18 or 0
icon_buf rd ICON*ICON
text_buf rb TEXT_CHARS * 4 + 1 ; UTF-8 takes up to 4 bytes
macro max_of name, [value] {
common name = 0
forward
if value > name
name = value
end if
}
max_of TAB_DATA, PROCS_DATA, DISKS_DATA, DRIVERS_DATA, AUTORUN_DATA
align 4
tab_data rb TAB_DATA ; data of the open tab
+240
View File
@@ -0,0 +1,240 @@
; The window: its colors, size and place, the panel and the tabs, then the
; panel of the open tab.
draw_window:
mcall SF_REDRAW, SSF_BEGIN_DRAW
mcall SF_STYLE_SETTINGS, SSF_GET_COLORS, sc, sizeof.system_colors
mov eax, [sc.work_button] ; its channels high to low: al, ah, dl
mov edx, eax
shr edx, 16
cmp al, ah
jae @f
xchg al, ah
@@:
cmp al, dl
jae @f
xchg al, dl
@@:
cmp ah, dl
jae @f
xchg ah, dl
@@:
movzx ecx, dl ; blue, green, red
shl ecx, 16
mov cx, ax
mov [sc.work_button], ecx
mov dl, al ; the low ones half the high one
shr dl, 1
movzx ecx, dl ; all low, then green, red high
imul ecx, 0x10101
mov [green], ecx
mov byte [green + 1], al
mov [red], ecx
mov byte [red + 2], al
mov eax, [sc.work] ; between the window and the panel
mov edx, [sc.work_light]
call mix
mov [mid], eax
mcall SF_GET_SCREEN_SIZE ; half the screen, the kernel takes
shr eax, 1 ; it the first time
xchg esi, eax
mcall SF_STYLE_SETTINGS, SSF_GET_SCREEN_AREA
mov edx, esi
shr edx, 16
mov ebp, MIN_W - 1
call .fit
xchg eax, ebx
movzx edx, si
and dh, 0x7F
mov ebp, MIN_H - 1
call .fit
xchg eax, ecx
mov edx, [sc.work]
or edx, WIN_STYLE
mcall SF_CREATE_WINDOW, , , , 0, sz_title
mcall SF_THREAD_INFO, pinfo, -1
test [pinfo.wnd_state], WND_ROLLED_UP
jnz .done
test [pinfo.wnd_state], WND_MAXIMIZED ; the size it gets
jnz .layout
mov edx, [pinfo.box.width] ; not smaller than the minimum
mov esi, [pinfo.box.height]
cmp edx, MIN_W - 1 ; the kernel keeps the size - 1
jae @f
mov edx, MIN_W - 1
@@:
cmp esi, MIN_H - 1
jae @f
mov esi, MIN_H - 1
@@:
cmp edx, [pinfo.box.width]
jne @f
cmp esi, [pinfo.box.height]
je .layout
@@:
mcall SF_CHANGE_WINDOW, -1, -1 ; it sends a new redraw
jmp .done
.layout:
mov eax, [pinfo.client_box.width]
lea ecx, [eax - PAD*2]
mov [area_w], ecx
mov [bar_right], eax
mov [bar_left], PAD
mov eax, [pinfo.client_box.height]
sub eax, PAD + BTN_H
mov [bar_y], eax
sub eax, AREA_Y + PAD
mov [area_h], eax
mov ebx, PAD shl 16
mov bx, word [area_w]
mov ecx, AREA_Y shl 16
mov cx, ax
mov edx, [sc.work_light]
call frame_rect
mov edx, [sc.work] ; around the tabs and the panel: above,
mov ebx, [area_w] ; below with the bar, left, right
add ebx, 2*PAD + 1
mcall SF_DRAW_RECT, , TOP
mov ecx, [bar_y]
sub ecx, PAD
shl ecx, 16
mov cx, 2*PAD + BTN_H + 1
mcall SF_DRAW_RECT
mov ecx, [area_h]
add ecx, (TOP shl 16) + TAB_H - 1
mov ebx, PAD
mcall SF_DRAW_RECT
mov ebx, [area_w]
add ebx, PAD
shl ebx, 16
mov bx, PAD + 1
mcall SF_DRAW_RECT
mov esi, [area_w] ; the tabs as wide as the panel, the
add esi, NTABS - 1 ; room left shared alike
xor ebp, ebp
@@:
call .content
sub esi, eax
inc ebp
cmp ebp, NTABS
jb @b
xchg eax, esi
xor edx, edx
mov ecx, NTABS
div ecx
xchg eax, esi
mov ebx, PAD shl 16
xor ebp, ebp
.tab:
call .content
add eax, esi
cmp ebp, NTABS - 1 ; the last one to the end of the panel
jne @f
mov eax, [area_w]
add eax, PAD
mov edx, ebx
shr edx, 16
sub eax, edx
@@:
mov bx, ax
call .draw
imul eax, ebx, 1 shl 16
lea ebx, [ebx + eax - 1 shl 16] ; neighbours share the border
inc ebp
cmp ebp, NTABS
jb .tab
mov eax, sz_shutdown ; at the right end
mov edx, BTN_SHUTDOWN
mov esi, [sc.work_graph]
call bar_button
imul esi, [cur_tab], sizeof.TAB ; the bar of the tab, then its
movzx esi, word [tabs + esi + TAB.bar] ; panel
call bar_draw
mov eax, TAB.draw
call tab_call
.done:
mcall SF_REDRAW, SSF_END_DRAW
ret
; eax = start shl 16 + end of the work area, edx = the size - 1 wanted,
; ebp = the least; out: eax = start shl 16 + size - 1 of the window in its
; middle
.fit:
cmp edx, ebp
jae @f
mov edx, ebp
@@:
movzx ecx, ax
shr eax, 16
sub ecx, eax
cmp edx, ecx
jb @f
mov edx, ecx
@@:
sub ecx, edx
shr ecx, 1
add eax, ecx
shl eax, 16
mov ax, dx
ret
.draw: ; the caption in the middle
pusha
mov ecx, (TOP shl 16) + TAB_H
mov esi, [sc.work_dark]
cmp ebp, [cur_tab]
jne @f
mov esi, [sc.work_light]
@@:
mov edx, esi
call frame_rect
lea edx, [ebp + BTN_TAB + BT_HIDE + BT_NOFRAME]
mcall SF_DEFINE_BUTTON
call .content
movzx ecx, bx
sub ecx, eax
shr ecx, 1
shl ecx, 16
add ebx, ecx
mov ecx, TOP shl 16
mov eax, [sc.work_text]
jmp bar_text ; as high as the bar items
; ebp = tab; out: edi -> its caption, eax = its width
.content:
imul edi, ebp, sizeof.TAB
movzx edi, word [tabs + edi + TAB.caption]
mov eax, edi
call text_width
ret