btop/src/btop_menu.cpp
aristocratos c0e17a64d3 Squashed commit of the following:
commit c2c4fe47db
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Nov 13 23:15:53 2021 +0100

    Changes from main + fixes

commit bd5d867089
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Nov 13 21:24:01 2021 +0100

    Fixes

commit dc5f0606cb
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Nov 13 20:51:06 2021 +0100

    Fixed leak in Proc::collect()

commit 8b59ab6e11
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Nov 13 19:59:56 2021 +0100

    Fixed process cpu usage calculation

commit 53c8a0325b
Author: aristocratos <admin@qvantnet.com>
Date:   Mon Oct 25 13:01:53 2021 +0200

    Cpu temp set to average of pACC and eACC for mac m1

commit 940cd0a513
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 24 21:12:16 2021 +0200

    limit cpu temp to 20

commit 254ceb9c2d
Author: aristocratos <admin@qvantnet.com>
Date:   Sun Oct 24 11:24:04 2021 +0200

    Fixed up Makefile

commit 6fa3bf41d7
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 21 13:12:45 2021 +0200

    Makefile fixed WARNFLAGS

commit 2c98e2ca29
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 21 13:08:12 2021 +0200

    Updated Makefile

commit e69780e9bc
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 20 23:26:09 2021 +0200

    fix build

commit de62167921
Merge: a590dd3 a0ee404
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 20 23:10:36 2021 +0200

    Merge branch 'main' into OSX

commit a590dd3f67
Author: aristocratos <admin@qvantnet.com>
Date:   Mon Oct 18 11:20:12 2021 +0200

    Ignore format-truncation

commit 4c30742d41
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 18 10:08:01 2021 +0200

    comments about temp sensors

commit 46030de77c
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 18 08:10:37 2021 +0200

    available = total - used

commit 4c228de0ef
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 17 22:19:41 2021 +0200

    use sysconf to get arg_max - seems simpler

commit c60fc29f0f
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 17 22:10:50 2021 +0200

    arg_max should be int on macos

commit 0b5a931a6d
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 17 22:01:42 2021 +0200

    only fetch max_args once

commit 71d5cd5fd9
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Oct 16 23:24:07 2021 +0200

    Reverted mutexes back to custom atomic bool based locks

commit 3f34a67df6
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 16 21:47:55 2021 +0200

    these helpers can be static

commit fc19c46c8a
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 16 21:44:49 2021 +0200

    code cleanup: put the code in .cpp to enable incremental build

commit c252c618c0
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 16 21:09:21 2021 +0200

    don't crash on intel

commit 9f88187c29
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 16 21:06:18 2021 +0200

    small improvement

commit 808f09c974
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 16 20:59:48 2021 +0200

    don't iterate 3 times

commit d8408336e3
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 16 20:59:27 2021 +0200

    remove debug

commit 4f078c3beb
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 13 23:38:27 2021 +0200

    more temperature (M1 + intel)

commit 289880aaa6
Merge: 88a2528 3ffb212
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Oct 16 19:37:09 2021 +0200

    Merge branch 'OSX' of github.com:aristocratos/btop into OSX

commit 88a2528ca3
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Oct 16 19:34:10 2021 +0200

    Merge changes from main

commit 3ffb21203a
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 16 19:20:45 2021 +0200

    release a bit more - still has negative temps for 2 cores on my system

commit 70b4871062
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Oct 16 01:59:44 2021 +0200

    Fixed leaks in Mem and attempt at fixing leaks in sensors.cpp

commit fbae907720
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Fri Oct 15 23:41:37 2021 +0200

    temperature sensors via IOKit

commit cef0f0a68d
Author: aristocratos <admin@qvantnet.com>
Date:   Fri Oct 15 18:39:17 2021 +0200

    Process command line arguments

commit 921cfa01ff
Author: aristocratos <admin@qvantnet.com>
Date:   Wed Oct 13 23:20:15 2021 +0200

    Re-enable setuid and set default SU_GROUP to wheel for OSX

commit a416c888c7
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 13 21:16:41 2021 +0200

    temperature

commit e7afe00ce7
Author: aristocratos <admin@qvantnet.com>
Date:   Wed Oct 13 12:54:43 2021 +0200

    Cpu usage working again

commit 4193ef8921
Author: aristocratos <admin@qvantnet.com>
Date:   Wed Oct 13 10:36:51 2021 +0200

    Fixed cpu lazy sorting

commit 93fcb6ff04
Author: aristocratos <admin@qvantnet.com>
Date:   Tue Oct 12 22:22:45 2021 +0200

    Update README.md

commit 683354cd2e
Merge: 8a399c4 6d724d6
Author: aristocratos <admin@qvantnet.com>
Date:   Tue Oct 12 22:19:30 2021 +0200

    Merge pull request #80 from ShrirajHegde/OSX

    Add github workflow for MacOS

commit 8a399c499a
Author: aristocratos <admin@qvantnet.com>
Date:   Tue Oct 12 21:50:46 2021 +0200

    pointer to smart pointer, first pass

commit 772605003a
Author: aristocratos <admin@qvantnet.com>
Date:   Tue Oct 12 18:54:38 2021 +0200

    Fixed detailed memory not updating

commit 28cb677533
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 11 22:19:25 2021 +0200

    more memory free-up - still leaks like crazy

commit 304457863f
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 11 21:48:07 2021 +0200

    more RAII cleanup

commit 82e2e3c55c
Author: aristocratos <admin@qvantnet.com>
Date:   Mon Oct 11 12:40:25 2021 +0200

    Removed non present cpu fields and fixed calculation for selectable cpu field graphs

commit 68603f2b37
Author: aristocratos <admin@qvantnet.com>
Date:   Mon Oct 11 10:57:04 2021 +0200

    RAII Wrappers for Cpu::get_battery()

commit d5cb24fbeb
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 10 20:23:11 2021 +0200

    RAII

commit 8fad5a61be
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 9 21:44:16 2021 +0200

    get more disk IO stats

commit 7fa903cf16
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 9 21:43:48 2021 +0200

    fix build

commit 98036db660
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 9 21:18:25 2021 +0200

    remove unnecessary uptime param

commit aae7ae35ca
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 9 21:07:23 2021 +0200

    remove debug logging

commit 5187420b04
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 9 21:06:43 2021 +0200

    fix process elapsed time

commit 89582c0ea6
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 9 21:06:29 2021 +0200

    don't double free

commit 6d724d6155
Author: Shriraj Hegde <shriraj.hegde@gmail.com>
Date:   Sat Oct 9 21:46:33 2021 +0530

    Change Upload filename

commit 4f94ecc8ad
Author: Shriraj Hegde <shriraj.hegde@gmail.com>
Date:   Sat Oct 9 21:40:11 2021 +0530

    Fix upload path

commit e1d6d0a1f2
Author: Shriraj Hegde <shriraj.hegde@gmail.com>
Date:   Sat Oct 9 21:36:13 2021 +0530

    Skip installing gcc via Homebrew
    Change job name

commit 02cdd9d759
Author: Shriraj Hegde <shriraj.hegde@gmail.com>
Date:   Sat Oct 9 21:30:40 2021 +0530

    Fix uploading
    Remove distclean

commit 39eb6c396f
Author: Shriraj Hegde <shriraj.hegde@gmail.com>
Date:   Sat Oct 9 21:26:57 2021 +0530

    Disable static compilation

commit 099592bccd
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Oct 9 17:52:10 2021 +0200

    Ignore empty pid 0 to fix tree mode

commit a28e17556e
Author: Shriraj Hegde <shriraj.hegde@gmail.com>
Date:   Sat Oct 9 21:17:11 2021 +0530

    Add workflow for MacOS

commit aee9179c0a
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Oct 9 17:36:46 2021 +0200

    Disable failed tty mode detection for OSX

commit 4b7b98058d
Author: aristocratos <admin@qvantnet.com>
Date:   Sat Oct 9 11:28:32 2021 +0200

    Fixed disk io and added io activity based on read/write

commit bfa0629e7d
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Fri Oct 8 22:28:10 2021 +0200

    fill in 0 for ioticks

commit a016ff8a03
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Fri Oct 8 22:16:01 2021 +0200

    disk io from IOreg. Does not show any io though

commit f98606c6db
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Fri Oct 8 09:32:06 2021 +0200

    per process IO stats

commit c8b50ed488
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Fri Oct 8 00:11:08 2021 +0200

    don't show autofs, it's useless

commit c4df64d440
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 7 18:41:49 2021 +0200

    Fixed compile time display for gmake and command timings

commit b3e6f495f7
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 7 18:26:15 2021 +0200

    Fixed clk_tck -> clkTck

commit e53799188f
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 7 18:25:14 2021 +0200

    Fixed better detection for OSX

commit b864edf984
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 7 18:24:37 2021 +0200

    Fixed cumulative cpu usage

commit 6a3c5d9b97
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 7 13:20:30 2021 +0200

    Proc::collect() better cpu percent accurazy

commit 84d0596294
Merge: 3564f8e 98e1e87
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 7 12:56:55 2021 +0200

    Merge branch 'OSX' of github.com:aristocratos/btop into OSX

commit 3564f8e4c2
Author: aristocratos <admin@qvantnet.com>
Date:   Thu Oct 7 12:56:27 2021 +0200

    Proc::collect() fixed cputimes and cpu percentage calc

commit 98e1e87405
Merge: 60c5636 d96fdd7
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Thu Oct 7 11:32:41 2021 +0200

    Merge branch 'main' into OSX

commit 60c5636cd7
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 22:45:54 2021 +0200

    fix warning

commit 489e446152
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 22:38:40 2021 +0200

    details + process states

commit 7e5a808c73
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 22:38:19 2021 +0200

    avoid details crash

commit 9c9da4606b
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 21:03:21 2021 +0200

    fix quit on macos

commit ec7415384d
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 00:41:37 2021 +0200

    fix mistake in makefile

commit 5ac8fa4c8a
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 18:56:13 2021 +0200

    don't show /dev

commit d901bbebd9
Author: aristocratos <gnmjpl@gmail.com>
Date:   Wed Oct 6 17:27:51 2021 +0200

     Ignore tags and other branches

commit c7f1e71e29
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 16:00:41 2021 +0200

    comment

commit b9d58e3faf
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 15:55:58 2021 +0200

    impossible to get CPU freq on M1 apparently

commit 66072711c2
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 15:33:43 2021 +0200

    detect full

commit 6bb0e930a2
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 00:38:46 2021 +0200

    CPU freq in GHz

commit a5f10f1a0f
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 15:13:18 2021 +0200

    check array length

commit 155c848b97
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 15:05:20 2021 +0200

    switch to other way to get CPU freq (still does not work)

commit cf51ba2ebe
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 14:45:44 2021 +0200

    remove some warnings

commit 775dff5f72
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 14:16:45 2021 +0200

    fix link

commit 8c67967775
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 14:16:38 2021 +0200

    reduce diff more

commit 70b47d2ca8
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 14:10:23 2021 +0200

    reduce diff with main branch

commit ca9cb48054
Merge: d0c6c0a c66b46f
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 13:49:20 2021 +0200

    Merge remote-tracking branch 'origin/main' into OSX

commit c66b46f850
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 13:41:57 2021 +0200

    battery state via CoreFoundation

commit d0c6c0a362
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 10:51:36 2021 +0200

    all disks + load averages

commit ca67526dc1
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 10:33:55 2021 +0200

    show all disks

commit 56119f99a9
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 00:17:41 2021 +0200

    procs sorting/filtering

commit 8d86011d72
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 23:42:17 2021 +0200

    battery states

commit a9b64d62e4
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 23:24:59 2021 +0200

    battery hack works on M1

commit ce51031142
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 23:18:22 2021 +0200

    ugly hack to get battery

commit d5e6725c6c
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 22:42:42 2021 +0200

    CPU stuff

commit 5c02bd8c83
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 21:25:42 2021 +0200

    network

commit d5da9d4983
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 15:43:05 2021 +0200

    correct cached size

commit 5f11aba504
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 12:03:48 2021 +0200

    vm stats from syscall + swap

commit 776fc96852
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 10:48:07 2021 +0200

    seems to work indeed

commit 7b40e2835a
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 10:46:14 2021 +0200

    allow override optimization flag

commit 005ea24e4c
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 10:09:24 2021 +0200

    update Makefile

commit af8cec9deb
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 4 15:32:55 2021 +0200

    some more params

commit 7ebe4f7594
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 4 15:15:55 2021 +0200

    show more disks

commit e50a56394a
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 4 14:52:56 2021 +0200

    disks show something

commit 6497a8c202
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 4 09:15:35 2021 +0200

    reformat

commit 28e152b80c
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 23:21:13 2021 +0200

    decrease diff with upstream

commit 40da88e9ca
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 22:56:14 2021 +0200

    try to get disks to show

commit eaf2bb56a5
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 22:42:01 2021 +0200

    don't crash on deque::back()

commit f66b6f712c
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 22:08:21 2021 +0200

    cpu freq, name & process uid/name

commit 34a8a61f4d
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 21:46:11 2021 +0200

    basic process info

commit 29bb2dcc5f
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 21:45:39 2021 +0200

    initialize mutex (needed on macos apparently and not on linux)

commit fb5970b000
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 2 23:53:41 2021 +0200

    comment

commit 49d16cdddd
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 2 23:51:29 2021 +0200

    extract delimiters

commit 3db9d66476
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 2 23:48:28 2021 +0200

    first infos on macos: memory used & free

commit f8acb2f854
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Sep 28 23:37:03 2021 +0200

    make it compile on macos (M1 - arm64). Does not run though

commit bbba17cd35
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 10:51:36 2021 +0200

    all disks + load averages

commit 548203e93d
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 10:33:55 2021 +0200

    show all disks

commit 0ab2be3985
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Oct 6 00:17:41 2021 +0200

    procs sorting/filtering

commit 096104c90b
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 23:42:17 2021 +0200

    battery states

commit 0ad93684c2
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 23:24:59 2021 +0200

    battery hack works on M1

commit c75b0f1cea
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 23:18:22 2021 +0200

    ugly hack to get battery

commit 600b4f72b3
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 22:42:42 2021 +0200

    CPU stuff

commit 4eb812d52c
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 21:25:42 2021 +0200

    network

commit 899be68a78
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 15:43:05 2021 +0200

    correct cached size

commit a1c7f935e3
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 12:03:48 2021 +0200

    vm stats from syscall + swap

commit bd1050a740
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 10:48:07 2021 +0200

    seems to work indeed

commit 5094b73758
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 10:46:14 2021 +0200

    allow override optimization flag

commit 8811270332
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Oct 5 10:09:24 2021 +0200

    update Makefile

commit 42f966f448
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 4 15:32:55 2021 +0200

    some more params

commit c1e6d6a62e
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 4 15:15:55 2021 +0200

    show more disks

commit 50fcdaa854
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 4 14:52:56 2021 +0200

    disks show something

commit 264bf2d7da
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Mon Oct 4 09:15:35 2021 +0200

    reformat

commit 1fd625086b
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 23:21:13 2021 +0200

    decrease diff with upstream

commit 17f9f3703c
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 22:56:14 2021 +0200

    try to get disks to show

commit 8462ae6431
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 22:42:01 2021 +0200

    don't crash on deque::back()

commit 78bce5b5a6
Merge: 53e379d f9505a4
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 22:08:34 2021 +0200

    Merge branch 'aristocratos:main' into main

commit 53e379d74d
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 22:08:21 2021 +0200

    cpu freq, name & process uid/name

commit 2a44b307ef
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 21:46:11 2021 +0200

    basic process info

commit 66534eb5b5
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sun Oct 3 21:45:39 2021 +0200

    initialize mutex (needed on macos apparently and not on linux)

commit 0983917f26
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 2 23:53:41 2021 +0200

    comment

commit 9732507248
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 2 23:51:29 2021 +0200

    extract delimiters

commit 6e704ce838
Merge: fe4db7c 7bfbd83
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 2 23:48:43 2021 +0200

    Merge branch 'main' of github.com:joske/btop

commit fe4db7c16c
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Sat Oct 2 23:48:28 2021 +0200

    first infos on macos: memory used & free

commit 7bfbd83a47
Merge: 8c8139b a15f961
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Fri Oct 1 17:05:26 2021 +0200

    Merge branch 'aristocratos:main' into main

commit 8c8139bd1d
Merge: 679d21c a246c09
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Sep 29 21:50:00 2021 +0200

    Merge branch 'aristocratos:main' into main

commit 679d21cd22
Merge: 4c70c5b a49b8f9
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Sep 29 20:23:34 2021 +0200

    Merge branch 'aristocratos:main' into main

commit 4c70c5bdd9
Merge: 84a9746 c70667e
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Wed Sep 29 08:30:05 2021 +0200

    Merge branch 'aristocratos:main' into main

commit 84a974695a
Author: Jos Dehaes <jos.dehaes@gmail.com>
Date:   Tue Sep 28 23:37:03 2021 +0200

    make it compile on macos (M1 - arm64). Does not run though

Co-authored-by: Jos Dehaes <jos.dehaes@gmail.com>
2021-11-13 23:37:23 +01:00

1395 lines
45 KiB
C++

/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
indent = tab
tab-size = 4
*/
#include <deque>
#include <robin_hood.h>
#include <array>
#include <ranges>
#include <signal.h>
#include <errno.h>
#include <cmath>
#include <filesystem>
#include <btop_menu.hpp>
#include <btop_tools.hpp>
#include <btop_config.hpp>
#include <btop_theme.hpp>
#include <btop_draw.hpp>
#include <btop_shared.hpp>
using std::deque, robin_hood::unordered_flat_map, std::array, std::views::iota, std::ref, std::max, std::min, std::ceil, std::clamp;
using namespace Tools;
namespace fs = std::filesystem;
namespace rng = std::ranges;
namespace Menu {
atomic<bool> active (false);
string bg;
bool redraw = true;
int currentMenu = -1;
msgBox messageBox;
int signalToSend = 0;
int signalKillRet = 0;
const array<string, 32> P_Signals = {
"0",
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL",
"SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE",
"SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2",
"SIGPIPE", "SIGALRM", "SIGTERM", "16", "SIGCHLD",
"SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN",
"SIGTTOU", "SIGURG", "SIGXCPU", "SIGXFSZ",
"SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO",
"SIGPWR", "SIGSYS"
};
unordered_flat_map<string, Input::Mouse_loc> mouse_mappings;
const array<array<string, 3>, 3> menu_normal = {
array<string, 3>{
"┌─┐┌─┐┌┬┐┬┌─┐┌┐┌┌─┐",
"│ │├─┘ │ ││ ││││└─┐",
"└─┘┴ ┴ ┴└─┘┘└┘└─┘"
},
{
"┬ ┬┌─┐┬ ┌─┐",
"├─┤├┤ │ ├─┘",
"┴ ┴└─┘┴─┘┴ "
},
{
"┌─┐ ┬ ┬ ┬┌┬┐",
"│─┼┐│ │ │ │ ",
"└─┘└└─┘ ┴ ┴ "
}
};
const array<array<string, 3>, 3> menu_selected = {
array<string, 3>{
"╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗",
"║ ║╠═╝ ║ ║║ ║║║║╚═╗",
"╚═╝╩ ╩ ╩╚═╝╝╚╝╚═╝"
},
{
"╦ ╦╔═╗╦ ╔═╗",
"╠═╣║╣ ║ ╠═╝",
"╩ ╩╚═╝╩═╝╩ "
},
{
"╔═╗ ╦ ╦ ╦╔╦╗ ",
"║═╬╗║ ║ ║ ║ ",
"╚═╝╚╚═╝ ╩ ╩ "
}
};
const array<int, 3> menu_width = {19, 12, 12};
const vector<array<string, 2>> help_text = {
{"Mouse 1", "Clicks buttons and selects in process list."},
{"Mouse scroll", "Scrolls any scrollable list/text under cursor."},
{"Esc, m", "Toggles main menu."},
{"p", "Cycle view presets forwards."},
{"shift + p", "Cycle view presets backwards."},
{"1", "Toggle CPU box."},
{"2", "Toggle MEM box."},
{"3", "Toggle NET box."},
{"4", "Toggle PROC box."},
{"d", "Toggle disks view in MEM box."},
{"F2, o", "Shows options."},
{"F1, h", "Shows this window."},
{"ctrl + z", "Sleep program and put in background."},
{"q, ctrl + c", "Quits program."},
{"+, -", "Add/Subtract 100ms to/from update timer."},
{"Up, Down", "Select in process list."},
{"Enter", "Show detailed information for selected process."},
{"Spacebar", "Expand/collapse the selected process in tree view."},
{"Pg Up, Pg Down", "Jump 1 page in process list."},
{"Home, End", "Jump to first or last page in process list."},
{"Left, Right", "Select previous/next sorting column."},
{"b, n", "Select previous/next network device."},
{"i", "Toggle disks io mode with big graphs."},
{"z", "Toggle totals reset for current network device"},
{"a", "Toggle auto scaling for the network graphs."},
{"y", "Toggle synced scaling mode for network graphs."},
{"f, /", "To enter a process filter."},
{"delete", "Clear any entered filter."},
{"c", "Toggle per-core cpu usage of processes."},
{"r", "Reverse sorting order in processes box."},
{"e", "Toggle processes tree view."},
{"Selected +, -", "Expand/collapse the selected process in tree view."},
{"Selected t", "Terminate selected process with SIGTERM - 15."},
{"Selected k", "Kill selected process with SIGKILL - 9."},
{"Selected s", "Select or enter signal to send to process."},
{"", " "},
{"", "For bug reporting and project updates, visit:"},
{"", "https://github.com/aristocratos/btop"},
};
const vector<vector<vector<string>>> categories = {
{
{"color_theme",
"Set color theme.",
"",
"Choose from all theme files in (usually)",
"\"/usr/[local/]share/btop/themes\" and",
"\"~/.config/btop/themes\".",
"",
"\"Default\" for builtin default theme.",
"\"TTY\" for builtin 16-color theme.",
"",
"For theme updates see:",
"https://github.com/aristocratos/btop"},
{"theme_background",
"If the theme set background should be shown.",
"",
"Set to False if you want terminal background",
"transparency."},
{"truecolor",
"Sets if 24-bit truecolor should be used.",
"",
"Will convert 24-bit colors to 256 color",
"(6x6x6 color cube) if False.",
"",
"Set to False if your terminal doesn't have",
"truecolor support and can't convert to",
"256-color."},
{"force_tty",
"TTY mode.",
"",
"Set to true to force tty mode regardless",
"if a real tty has been detected or not.",
"",
"Will force 16-color mode and TTY theme,",
"set all graph symbols to \"tty\" and swap",
"out other non tty friendly symbols."},
{"vim_keys",
"Enable vim keys.",
"Set to True to enable \"h,j,k,l\" keys for",
"directional control in lists.",
"",
"Conflicting keys for",
"h (help) and k (kill)",
"is accessible while holding shift."},
{"presets",
"Define presets for the layout of the boxes.",
"",
"Preset 0 is always all boxes shown with",
"default settings.",
"Max 9 presets.",
"",
"Format: \"box_name:P:G,box_name:P:G\"",
"P=(0 or 1) for alternate positons.",
"G=graph symbol to use for box.",
"",
"Use withespace \" \" as seprator between",
"different presets.",
"",
"Example:",
"\"mem:0:tty,proc:1:default cpu:0:braille\""},
{"shown_boxes",
"Manually set which boxes to show.",
"",
"Available values are \"cpu mem net proc\".",
"Seperate values with whitespace.",
"",
"Toggle between presets with key \"p\"."},
{"update_ms",
"Update time in milliseconds.",
"",
"Recommended 2000 ms or above for better",
"sample times for graphs.",
"",
"Min value: 100 ms",
"Max value: 86400000 ms = 24 hours."},
{"rounded_corners",
"Rounded corners on boxes.",
"",
"True or False",
"",
"Is always False if TTY mode is ON."},
{"graph_symbol",
"Default symbols to use for graph creation.",
"",
"\"braille\", \"block\" or \"tty\".",
"",
"\"braille\" offers the highest resolution but",
"might not be included in all fonts.",
"",
"\"block\" has half the resolution of braille",
"but uses more common characters.",
"",
"\"tty\" uses only 3 different symbols but will",
"work with most fonts.",
"",
"Note that \"tty\" only has half the horizontal",
"resolution of the other two,",
"so will show a shorter historical view."},
{"clock_format",
"Draw a clock at top of screen.",
"(Only visible if cpu box is enabled!)",
"",
"Formatting according to strftime, empty",
"string to disable.",
"",
"Custom formatting options:",
"\"/host\" = hostname",
"\"/user\" = username",
"\"/uptime\" = system uptime",
"",
"Examples of strftime formats:",
"\"%X\" = locale HH:MM:SS",
"\"%H\" = 24h hour, \"%I\" = 12h hour",
"\"%M\" = minute, \"%S\" = second",
"\"%d\" = day, \"%m\" = month, \"%y\" = year"},
{"background_update",
"Update main ui when menus are showing.",
"",
"True or False.",
"",
"Set this to false if the menus is flickering",
"too much for a comfortable experience."},
{"show_battery",
"Show battery stats.",
"(Only visible if cpu box is enabled!)",
"",
"Show battery stats in the top right corner",
"if a battery is present."},
{"selected_battery",
"Select battery.",
"",
"Which battery to use if multiple are present.",
"Can be both batteries and UPS.",
"",
"\"Auto\" for auto detection."},
{"log_level",
"Set loglevel for error.log",
"",
"\"ERROR\", \"WARNING\", \"INFO\" and \"DEBUG\".",
"",
"The level set includes all lower levels,",
"i.e. \"DEBUG\" will show all logging info."}
},
{
{"cpu_bottom",
"Cpu box location.",
"",
"Show cpu box at bottom of screen instead",
"of top."},
{"graph_symbol_cpu",
"Graph symbol to use for graphs in cpu box.",
"",
"\"default\", \"braille\", \"block\" or \"tty\".",
"",
"\"default\" for the general default symbol.",},
{"cpu_graph_upper",
"Cpu upper graph.",
"",
"Sets the CPU stat shown in upper half of",
"the CPU graph.",
"",
"\"total\" = Total cpu usage.",
"\"user\" = User mode cpu usage.",
"\"system\" = Kernel mode cpu usage.",
"+ more depending on kernel."},
{"cpu_graph_lower",
"Cpu lower graph.",
"",
"Sets the CPU stat shown in lower half of",
"the CPU graph.",
"",
"\"total\" = Total cpu usage.",
"\"user\" = User mode cpu usage.",
"\"system\" = Kernel mode cpu usage.",
"+ more depending on kernel."},
{"cpu_invert_lower",
"Toggles orientation of the lower CPU graph.",
"",
"True or False."},
{"cpu_single_graph",
"Completely disable the lower CPU graph.",
"",
"Shows only upper CPU graph and resizes it",
"to fit to box height.",
"",
"True or False."},
{"check_temp",
"Enable cpu temperature reporting.",
"",
"True or False."},
{"cpu_sensor",
"Cpu temperature sensor",
"",
"Select the sensor that corresponds to",
"your cpu temperature.",
"",
"Set to \"Auto\" for auto detection."},
{"show_coretemp",
"Show temperatures for cpu cores.",
"",
"Only works if check_temp is True and",
"the system is reporting core temps."},
{"cpu_core_map",
"Custom mapping between core and coretemp.",
"",
"Can be needed on certain cpus to get correct",
"temperature for correct core.",
"",
"Use lm-sensors or similar to see which cores",
"are reporting temperatures on your machine.",
"",
"Format: \"X:Y\"",
"X=core with wrong temp.",
"Y=core with correct temp.",
"Use space as separator between multiple",
"entries.",
"",
"Example: \"4:0 5:1 6:3\""},
{"temp_scale",
"Which temperature scale to use.",
"",
"Celsius, default scale.",
"",
"Fahrenheit, the american one.",
"",
"Kelvin, 0 = absolute zero, 1 degree change",
"equals 1 degree change in Celsius.",
"",
"Rankine, 0 = abosulte zero, 1 degree change",
"equals 1 degree change in Fahrenheit."},
{"show_cpu_freq",
"Show CPU frequency",
"",
"Can cause slowdowns on systems with many",
"cores and certain kernel versions."},
{"custom_cpu_name",
"Custom cpu model name in cpu percentage box.",
"",
"Empty string to disable."},
{"show_uptime",
"Shows the system uptime in the CPU box.",
"",
"Can also be shown in the clock by using",
"\"/uptime\" in the formatting.",
"",
"True or False."},
},
{
{"mem_below_net",
"Mem box location.",
"",
"Show mem box below net box instead of above."},
{"graph_symbol_mem",
"Graph symbol to use for graphs in mem box.",
"",
"\"default\", \"braille\", \"block\" or \"tty\".",
"",
"\"default\" for the general default symbol.",},
{"mem_graphs",
"Show graphs for memory values.",
"",
"True or False."},
{"show_disks",
"Split memory box to also show disks.",
"",
"True or False."},
{"show_io_stat",
"Toggle IO activity graphs.",
"",
"Show small IO graphs that for disk activity",
"(disk busy time) when not in IO mode.",
"",
"True or False."},
{"io_mode",
"Toggles io mode for disks.",
"",
"Shows big graphs for disk read/write speeds",
"instead of used/free percentage meters.",
"",
"True or False."},
{"io_graph_combined",
"Toggle combined read and write graphs.",
"",
"Only has effect if \"io mode\" is True.",
"",
"True or False."},
{"io_graph_speeds",
"Set top speeds for the io graphs.",
"",
"Manually set which speed in MiB/s that",
"equals 100 percent in the io graphs.",
"(100 MiB/s by default).",
"",
"Format: \"device:speed\" seperate disks with",
"whitespace \" \".",
"",
"Example: \"/dev/sda:100, /dev/sdb:20\"."},
{"show_swap",
"If swap memory should be shown in memory box.",
"",
"True or False."},
{"swap_disk",
"Show swap as a disk.",
"",
"Ignores show_swap value above.",
"Inserts itself after first disk."},
{"only_physical",
"Filter out non physical disks.",
"",
"Set this to False to include network disks,",
"RAM disks and similar.",
"",
"True or False."},
{"use_fstab",
"Read disks list from /etc/fstab.",
"(Has no effect on macOS X)",
"",
"This also disables only_physical.",
"",
"True or False."},
{"disks_filter",
"Optional filter for shown disks.",
"",
"Should be full path of a mountpoint.",
"Separate multiple values with",
"whitespace \" \".",
"",
"Begin line with \"exclude=\" to change to",
"exclude filter.",
"Oterwise defaults to \"most include\" filter.",
"",
"Example:",
"\"exclude=/boot /home/user\""},
},
{
{"graph_symbol_net",
"Graph symbol to use for graphs in net box.",
"",
"\"default\", \"braille\", \"block\" or \"tty\".",
"",
"\"default\" for the general default symbol.",},
{"net_download",
"Fixed network graph download value.",
"",
"Value in Mebibytes, default \"100\".",
"",
"Can be toggled with auto button."},
{"net_upload",
"Fixed network graph upload value.",
"",
"Value in Mebibytes, default \"100\".",
"",
"Can be toggled with auto button."},
{"net_auto",
"Start in network graphs auto rescaling mode.",
"",
"Ignores any values set above at start and",
"rescales down to 10Kibibytes at the lowest.",
"",
"True or False."},
{"net_sync",
"Network scale sync.",
"",
"Syncs the scaling for download and upload to",
"whichever currently has the highest scale.",
"",
"True or False."},
{"net_iface",
"Network Interface.",
"",
"Manually set the starting Network Interface.",
"",
"Will otherwise automatically choose the NIC",
"with the highest total download since boot."},
},
{
{"proc_left",
"Proc box location.",
"",
"Show proc box on left side of screen",
"instead of right."},
{"graph_symbol_proc",
"Graph symbol to use for graphs in proc box.",
"",
"\"default\", \"braille\", \"block\" or \"tty\".",
"",
"\"default\" for the general default symbol.",},
{"proc_sorting",
"Processes sorting option.",
"",
"Possible values:",
"\"pid\", \"program\", \"arguments\", \"threads\",",
"\"user\", \"memory\", \"cpu lazy\" and",
"\"cpu responsive\".",
"",
"\"cpu lazy\" updates top process over time.",
"\"cpu responsive\" updates top process",
"directly."},
{"proc_reversed",
"Reverse processes sorting order.",
"",
"True or False."},
{"proc_tree",
"Processes tree view.",
"",
"Set true to show processes grouped by",
"parents with lines drawn between parent",
"and child process."},
{"proc_colors",
"Enable colors in process view.",
"",
"True or False."},
{"proc_gradient",
"Enable process view gradient fade.",
"",
"Fades from top or current selection.",
"Max fade value is equal to current themes",
"\"inactive_fg\" color value."},
{"proc_per_core",
"Process usage per core.",
"",
"If process cpu usage should be of the core",
"it's running on or usage of the total",
"available cpu power.",
"",
"If true and process is multithreaded",
"cpu usage can reach over 100%."},
{"proc_mem_bytes",
"Show memory as bytes in process list.",
" ",
"Will show percentage of total memory",
"if False."},
}
};
msgBox::msgBox() {}
msgBox::msgBox(int width, int boxtype, vector<string> content, string title)
: width(width), boxtype(boxtype) {
const auto& tty_mode = Config::getB("tty_mode");
const auto& rounded = Config::getB("rounded_corners");
const auto& right_up = (tty_mode or not rounded ? Symbols::right_up : Symbols::round_right_up);
const auto& left_up = (tty_mode or not rounded ? Symbols::left_up : Symbols::round_left_up);
const auto& right_down = (tty_mode or not rounded ? Symbols::right_down : Symbols::round_right_down);
const auto& left_down = (tty_mode or not rounded ? Symbols::left_down : Symbols::round_left_down);
height = content.size() + 7;
x = Term::width / 2 - width / 2;
y = Term::height/2 - height/2;
if (boxtype == 2) selected = 1;
button_left = left_up + Symbols::h_line * 6 + Mv::l(7) + Mv::d(2) + left_down + Symbols::h_line * 6 + Mv::l(7) + Mv::u(1) + Symbols::v_line;
button_right = Symbols::v_line + Mv::l(7) + Mv::u(1) + Symbols::h_line * 6 + right_up + Mv::l(7) + Mv::d(2) + Symbols::h_line * 6 + right_down + Mv::u(2);
box_contents = Draw::createBox(x, y, width, height, Theme::c("hi_fg"), true, title) + Mv::d(1);
for (const auto& line : content) {
box_contents += Mv::save + Mv::r(width / 2 - Fx::uncolor(line).size() / 2 - 1) + line + Mv::restore + Mv::d(1);
}
}
string msgBox::operator()() {
string out;
int pos = width / 2 - (boxtype == 0 ? 6 : 14);
auto& first_color = (selected == 0 ? Theme::c("hi_fg") : Theme::c("div_line"));
out = Mv::d(1) + Mv::r(pos) + Fx::b + first_color + button_left + (selected == 0 ? Theme::c("title") : Theme::c("main_fg") + Fx::ub)
+ (boxtype == 0 ? " Ok " : " Yes ") + first_color + button_right;
mouse_mappings["button1"] = Input::Mouse_loc{y + height - 4, x + pos + 1, 3, 12 + (boxtype > 0 ? 1 : 0)};
if (boxtype > 0) {
auto& second_color = (selected == 1 ? Theme::c("hi_fg") : Theme::c("div_line"));
out += Mv::r(2) + second_color + button_left + (selected == 1 ? Theme::c("title") : Theme::c("main_fg") + Fx::ub)
+ " No " + second_color + button_right;
mouse_mappings["button2"] = Input::Mouse_loc{y + height - 4, x + pos + 15 + (boxtype > 0 ? 1 : 0), 3, 12};
}
return box_contents + out + Fx::reset;
}
//? Process input
int msgBox::input(string key) {
if (key.empty()) return Invalid;
if (is_in(key, "escape", "backspace", "q") or key == "button2") {
return No_Esc;
}
else if (key == "button1" or (boxtype == 0 and str_to_upper(key) == "O")) {
return Ok_Yes;
}
else if (is_in(key, "enter", "space")) {
return selected + 1;
}
else if (boxtype == 0) {
return Invalid;
}
else if (str_to_upper(key) == "Y") {
return Ok_Yes;
}
else if (str_to_upper(key) == "N") {
return No_Esc;
}
else if (is_in(key, "right", "tab")) {
if (++selected > 1) selected = 0;
return Select;
}
else if (is_in(key, "left", "shift_tab")) {
if (--selected < 0) selected = 1;
return Select;
}
return Invalid;
}
void msgBox::clear() {
box_contents.clear();
box_contents.shrink_to_fit();
button_left.clear();
button_left.shrink_to_fit();
button_right.clear();
button_right.shrink_to_fit();
if (mouse_mappings.contains("button1")) mouse_mappings.erase("button1");
if (mouse_mappings.contains("button2")) mouse_mappings.erase("button2");
}
enum menuReturnCodes {
NoChange,
Changed,
Closed,
Switch
};
int signalChoose(const string& key) {
auto& s_pid = (Config::getB("show_detailed") and Config::getI("selected_pid") == 0 ? Config::getI("detailed_pid") : Config::getI("selected_pid"));
static int x = 0, y = 0, selected_signal = -1;
if (bg.empty()) selected_signal = -1;
auto& out = Global::overlay;
int retval = Changed;
if (redraw) {
x = Term::width/2 - 40;
y = Term::height/2 - 9;
bg = Draw::createBox(x + 2, y, 78, 18, Theme::c("hi_fg"), true, "signals");
bg += Mv::to(y+2, x+3) + Theme::c("title") + Fx::b + cjust("Send signal to PID " + to_string(s_pid) + " ("
+ uresize((s_pid == Config::getI("detailed_pid") ? Proc::detailed.entry.name : Config::getS("selected_name")), 30) + ")", 76);
}
else if (is_in(key, "escape", "q")) {
return Closed;
}
else if (key.starts_with("button_")) {
if (int new_select = stoi(key.substr(7)); new_select == selected_signal)
goto ChooseEntering;
else
selected_signal = new_select;
}
else if (is_in(key, "enter", "space") and selected_signal >= 0) {
ChooseEntering:
signalKillRet = 0;
if (s_pid < 1) {
signalKillRet = ESRCH;
menuMask.set(SignalReturn);
}
else if (kill(s_pid, selected_signal) != 0) {
signalKillRet = errno;
menuMask.set(SignalReturn);
}
return Closed;
}
else if (key.size() == 1 and isdigit(key.at(0)) and selected_signal < 10) {
selected_signal = std::min(std::stoi((selected_signal < 1 ? key : to_string(selected_signal) + key)), 64);
}
else if (key == "backspace" and selected_signal != -1) {
selected_signal = (selected_signal < 10 ? -1 : selected_signal / 10);
}
else if (is_in(key, "up", "k") and selected_signal != 16) {
if (selected_signal == 1) selected_signal = 31;
else if (selected_signal < 6) selected_signal += 25;
else {
bool offset = (selected_signal > 16);
selected_signal -= 5;
if (selected_signal <= 16 and offset) selected_signal--;
}
}
else if (is_in(key, "down", "j")) {
if (selected_signal == 31) selected_signal = 1;
else if (selected_signal < 1 or selected_signal == 16) selected_signal = 1;
else if (selected_signal > 26) selected_signal -= 25;
else {
bool offset = (selected_signal < 16);
selected_signal += 5;
if (selected_signal >= 16 and offset) selected_signal++;
if (selected_signal > 31) selected_signal = 31;
}
}
else if (is_in(key, "left", "h") and selected_signal > 0 and selected_signal != 16) {
if (--selected_signal < 1) selected_signal = 31;
else if (selected_signal == 16) selected_signal--;
}
else if (is_in(key, "right", "l") and selected_signal <= 31 and selected_signal != 16) {
if (++selected_signal > 31) selected_signal = 1;
else if (selected_signal == 16) selected_signal++;
}
else {
retval = NoChange;
}
if (retval == Changed) {
int cy = y+4, cx = x+4;
out = bg + Mv::to(cy++, x+3) + Theme::c("main_fg") + Fx::ub
+ rjust("Enter signal number: ", 48) + Theme::c("hi_fg") + (selected_signal >= 0 ? to_string(selected_signal) : "") + Theme::c("main_fg") + Fx::bl + "" + Fx::ubl;
auto sig_str = to_string(selected_signal);
for (int count = 0, i = 0; const auto& sig : P_Signals) {
if (count == 0 or count == 16) { count++; continue; }
if (i++ % 5 == 0) { ++cy; cx = x+4; }
out += Mv::to(cy, cx);
if (count == selected_signal) out += Theme::c("selected_bg") + Theme::c("selected_fg") + Fx::b + ljust(to_string(count), 3) + ljust('(' + sig + ')', 12) + Fx::reset;
else out += Theme::c("hi_fg") + ljust(to_string(count), 3) + Theme::c("main_fg") + ljust('(' + sig + ')', 12);
if (redraw) mouse_mappings["button_" + to_string(count)] = {cy, cx, 1, 15};
count++;
cx += 15;
}
cy++;
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ENTER", 38) + Theme::c("main_fg") + Fx::ub + " | To send signal.";
mouse_mappings["enter"] = {cy, x, 1, 78};
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust( "↑ ↓ ← →", 38, true) + Theme::c("main_fg") + Fx::ub + " | To choose signal.";
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ESC or \"q\"", 38) + Theme::c("main_fg") + Fx::ub + " | To abort.";
mouse_mappings["escape"] = {cy, x, 1, 78};
out += Fx::reset;
}
return (redraw ? Changed : retval);
}
int sizeError(const string& key) {
if (redraw) {
vector<string> cont_vec;
cont_vec.push_back(Fx::b + Theme::g("used")[100] + "Error:" + Theme::c("main_fg") + Fx::ub);
cont_vec.push_back("Terminal size to small to" + Fx::reset);
cont_vec.push_back("display menu or box!" + Fx::reset);
messageBox = Menu::msgBox{45, 0, cont_vec, "error"};
Global::overlay = messageBox();
}
auto ret = messageBox.input(key);
if (ret == msgBox::Ok_Yes or ret == msgBox::No_Esc) {
messageBox.clear();
return Closed;
}
else if (redraw) {
return Changed;
}
return NoChange;
}
int signalSend(const string& key) {
auto& s_pid = (Config::getB("show_detailed") and Config::getI("selected_pid") == 0 ? Config::getI("detailed_pid") : Config::getI("selected_pid"));
if (s_pid == 0) return Closed;
if (redraw) {
atomic_wait(Runner::active);
auto& p_name = (s_pid == Config::getI("detailed_pid") ? Proc::detailed.entry.name : Config::getS("selected_name"));
vector<string> cont_vec = {
Fx::b + Theme::c("main_fg") + "Send signal: " + Fx::ub + Theme::c("hi_fg") + to_string(signalToSend)
+ (signalToSend > 0 and signalToSend <= 32 ? Theme::c("main_fg") + " (" + P_Signals.at(signalToSend) + ')' : ""),
Fx::b + Theme::c("main_fg") + "To PID: " + Fx::ub + Theme::c("hi_fg") + to_string(s_pid) + Theme::c("main_fg") + " ("
+ uresize(p_name, 16) + ')' + Fx::reset,
};
messageBox = Menu::msgBox{50, 1, cont_vec, (signalToSend > 1 and signalToSend <= 32 and signalToSend != 17 ? P_Signals.at(signalToSend) : "signal")};
Global::overlay = messageBox();
}
auto ret = messageBox.input(key);
if (ret == msgBox::Ok_Yes) {
signalKillRet = 0;
if (kill(s_pid, signalToSend) != 0) {
signalKillRet = errno;
menuMask.set(SignalReturn);
}
messageBox.clear();
return Closed;
}
else if (ret == msgBox::No_Esc) {
messageBox.clear();
return Closed;
}
else if (ret == msgBox::Select) {
Global::overlay = messageBox();
return Changed;
}
else if (redraw) {
return Changed;
}
return NoChange;
}
int signalReturn(const string& key) {
if (redraw) {
vector<string> cont_vec;
cont_vec.push_back(Fx::b + Theme::g("used")[100] + "Failure:" + Theme::c("main_fg") + Fx::ub);
if (signalKillRet == EINVAL) {
cont_vec.push_back("Unsupported signal!" + Fx::reset);
}
else if (signalKillRet == EPERM) {
cont_vec.push_back("Insufficient permissions to send signal!" + Fx::reset);
}
else if (signalKillRet == ESRCH) {
cont_vec.push_back("Process not found!" + Fx::reset);
}
else {
cont_vec.push_back("Unknown error! (errno: " + to_string(signalKillRet) + ')' + Fx::reset);
}
messageBox = Menu::msgBox{50, 0, cont_vec, "error"};
Global::overlay = messageBox();
}
auto ret = messageBox.input(key);
if (ret == msgBox::Ok_Yes or ret == msgBox::No_Esc) {
messageBox.clear();
return Closed;
}
else if (redraw) {
return Changed;
}
return NoChange;
}
int mainMenu(const string& key) {
enum MenuItems { Options, Help, Quit };
static int y = 0, selected = 0;
static vector<string> colors_selected;
static vector<string> colors_normal;
auto& tty_mode = Config::getB("tty_mode");
if (bg.empty()) selected = 0;
int retval = Changed;
if (redraw) {
y = Term::height/2 - 10;
bg = Draw::banner_gen(y, 0, true);
if (not tty_mode) {
colors_selected = {
Theme::hex_to_color(Global::Banner_src.at(0).at(0)),
Theme::hex_to_color(Global::Banner_src.at(2).at(0)),
Theme::hex_to_color(Global::Banner_src.at(4).at(0))
};
colors_normal = {
Theme::hex_to_color("#CC"),
Theme::hex_to_color("#AA"),
Theme::hex_to_color("#80")
};
}
}
else if (is_in(key, "escape", "q", "m", "mouse_click")) {
return Closed;
}
else if (key.starts_with("button_")) {
if (int new_select = key.back() - '0'; new_select == selected)
goto MainEntering;
else
selected = new_select;
}
else if (is_in(key, "enter", "space")) {
MainEntering:
switch (selected) {
case Options:
menuMask.set(Menus::Options);
currentMenu = Menus::Options;
return Switch;
case Help:
menuMask.set(Menus::Help);
currentMenu = Menus::Help;
return Switch;
case Quit:
clean_quit(0);
}
}
else if (is_in(key, "down", "tab", "mouse_scroll_down", "j")) {
if (++selected > 2) selected = 0;
}
else if (is_in(key, "up", "shift_tab", "mouse_scroll_up", "k")) {
if (--selected < 0) selected = 2;
}
else {
retval = NoChange;
}
if (retval == Changed) {
auto& out = Global::overlay;
out = bg + Fx::reset + Fx::b;
auto cy = y + 7;
for (const auto& i : iota(0, 3)) {
if (tty_mode) out += (i == selected ? Theme::c("hi_fg") : Theme::c("main_fg"));
const auto& menu = (not tty_mode and i == selected ? menu_selected[i] : menu_normal[i]);
const auto& colors = (i == selected ? colors_selected : colors_normal);
if (redraw) mouse_mappings["button_" + to_string(i)] = {cy, Term::width/2 - menu_width[i]/2, 3, menu_width[i]};
for (int ic = 0; const auto& line : menu) {
out += Mv::to(cy++, Term::width/2 - menu_width[i]/2) + (tty_mode ? "" : colors[ic++]) + line;
}
}
out += Fx::reset;
}
return (redraw ? Changed : retval);
}
int optionsMenu(const string& key) {
enum Predispositions { isBool, isInt, isString, is2D, isBrowseable, isEditable};
static int y = 0, x = 0, height = 0, page = 0, pages = 0, selected = 0, select_max = 0, item_height = 0, selected_cat = 0, max_items = 0, last_sel = 0;
static bool editing = false;
static Draw::TextEdit editor;
static string warnings;
static bitset<8> selPred;
static const unordered_flat_map<string, std::reference_wrapper<const vector<string>>> optionsList = {
{"color_theme", std::cref(Theme::themes)},
{"log_level", std::cref(Logger::log_levels)},
{"temp_scale", std::cref(Config::temp_scales)},
{"proc_sorting", std::cref(Proc::sort_vector)},
{"graph_symbol", std::cref(Config::valid_graph_symbols)},
{"graph_symbol_cpu", std::cref(Config::valid_graph_symbols_def)},
{"graph_symbol_mem", std::cref(Config::valid_graph_symbols_def)},
{"graph_symbol_net", std::cref(Config::valid_graph_symbols_def)},
{"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)},
{"cpu_graph_upper", std::cref(Cpu::available_fields)},
{"cpu_graph_lower", std::cref(Cpu::available_fields)},
{"cpu_sensor", std::cref(Cpu::available_sensors)},
{"selected_battery", std::cref(Config::available_batteries)},
};
auto& tty_mode = Config::getB("tty_mode");
auto& vim_keys = Config::getB("vim_keys");
if (max_items == 0) {
for (const auto& cat : categories) {
if ((int)cat.size() > max_items) max_items = cat.size();
}
}
if (bg.empty()) {
page = selected = selected_cat = last_sel = 0;
redraw = true;
Theme::updateThemes();
}
int retval = Changed;
bool recollect = false;
bool screen_redraw = false;
bool theme_refresh = false;
//? Draw background if needed else process input
if (redraw) {
mouse_mappings.clear();
selPred.reset();
y = max(1, Term::height/2 - 3 - max_items);
x = Term::width/2 - 39;
height = min(Term::height - 7, max_items * 2 + 4);
if (height % 2 != 0) height--;
bg = Draw::banner_gen(y, 0, true)
+ Draw::createBox(x, y + 6, 78, height, Theme::c("hi_fg"), true, "tab" + Symbols::right)
+ Mv::to(y+8, x) + Theme::c("hi_fg") + Symbols::div_left + Theme::c("div_line") + Symbols::h_line * 29
+ Symbols::div_up + Symbols::h_line * (78 - 32) + Theme::c("hi_fg") + Symbols::div_right
+ Mv::to(y+6+height - 1, x+30) + Symbols::div_down + Theme::c("div_line");
for (const auto& i : iota(0, height - 4)) {
bg += Mv::to(y+9 + i, x + 30) + Symbols::v_line;
}
}
else if (not warnings.empty() and not key.empty()) {
auto ret = messageBox.input(key);
if (ret == msgBox::msgReturn::Ok_Yes or ret == msgBox::msgReturn::No_Esc) {
warnings.clear();
messageBox.clear();
}
}
else if (editing and not key.empty()) {
if (is_in(key, "escape", "mouse_click")) {
editor.clear();
editing = false;
}
else if (key == "enter") {
const auto& option = categories[selected_cat][item_height * page + selected][0];
if (selPred.test(isString) and Config::stringValid(option, editor.text)) {
Config::set(option, editor.text);
if (option == "custom_cpu_name") screen_redraw = true;
else if (is_in(option, "shown_boxes", "presets")) {
screen_redraw = true;
Config::current_preset = -1;
}
else if (option == "clock_format") {
Draw::update_clock(true);
screen_redraw = true;
}
else if (option == "cpu_core_map") {
atomic_wait(Runner::active);
Cpu::core_mapping = Cpu::get_core_mapping();
}
}
else if (selPred.test(isInt) and Config::intValid(option, editor.text)) {
Config::set(option, stoi(editor.text));
}
else
warnings = Config::validError;
editor.clear();
editing = false;
}
else if (not editor.command(key))
retval = NoChange;
}
else if (key == "mouse_click") {
const auto [mouse_x, mouse_y] = Input::mouse_pos;
if (mouse_x < x or mouse_x > x + 80 or mouse_y < y + 6 or mouse_y > y + 6 + height) {
return Closed;
}
else if (mouse_x < x + 30 and mouse_y > y + 8) {
auto m_select = ceil((double)(mouse_y - y - 8) / 2) - 1;
if (selected != m_select)
selected = m_select;
else if (selPred.test(isEditable))
goto mouseEnter;
else retval = NoChange;
}
}
else if (is_in(key, "enter", "e", "E") and selPred.test(isEditable)) {
mouseEnter:
const auto& option = categories[selected_cat][item_height * page + selected][0];
editor = Draw::TextEdit{Config::getAsString(option), selPred.test(isInt)};
editing = true;
mouse_mappings.clear();
}
else if (is_in(key, "escape", "q", "o", "backspace")) {
return Closed;
}
else if (is_in(key, "down", "mouse_scroll_down") or (vim_keys and key == "j")) {
if (++selected > select_max or selected >= item_height) {
if (page < pages - 1) page++;
else if (pages > 1) page = 0;
selected = 0;
}
}
else if (is_in(key, "up", "mouse_scroll_up") or (vim_keys and key == "k")) {
if (--selected < 0) {
if (page > 0) page--;
else if (pages > 1) page = pages - 1;
selected = item_height - 1;
}
}
else if (pages > 1 and key == "page_down") {
if (++page >= pages) page = 0;
selected = 0;
}
else if (pages > 1 and key == "page_up") {
if (--page < 0) page = pages - 1;
selected = 0;
}
else if (key == "tab") {
if (++selected_cat >= (int)categories.size()) selected_cat = 0;
page = selected = 0;
}
else if (key == "shift_tab") {
if (--selected_cat < 0) selected_cat = (int)categories.size() - 1;
page = selected = 0;
}
else if (is_in(key, "1", "2", "3", "4", "5") or key.starts_with("select_cat_")) {
selected_cat = key.back() - '0' - 1;
page = selected = 0;
}
else if (is_in(key, "left", "right") or (vim_keys and is_in(key, "h", "l"))) {
const auto& option = categories[selected_cat][item_height * page + selected][0];
if (selPred.test(isInt)) {
const int mod = (option == "update_ms" ? 100 : 1);
long value = Config::getI(option);
if (key == "right" or (vim_keys and key == "l")) value += mod;
else value -= mod;
if (Config::intValid(option, to_string(value)))
Config::set(option, static_cast<int>(value));
else {
warnings = Config::validError;
}
}
else if (selPred.test(isBool)) {
Config::flip(option);
screen_redraw = true;
if (option == "truecolor") {
theme_refresh = true;
Config::flip("lowcolor");
}
else if (option == "force_tty") {
theme_refresh = true;
Config::flip("tty_mode");
}
else if (is_in(option, "rounded_corners", "theme_background"))
theme_refresh = true;
else if (option == "background_update") {
Runner::pause_output = false;
}
}
else if (selPred.test(isBrowseable)) {
auto& optList = optionsList.at(option).get();
int i = v_index(optList, Config::getS(option));
if ((key == "right" or (vim_keys and key == "l")) and ++i >= (int)optList.size()) i = 0;
else if ((key == "left" or (vim_keys and key == "h")) and --i < 0) i = optList.size() - 1;
Config::set(option, optList.at(i));
if (option == "color_theme")
theme_refresh = true;
else if (option == "log_level") {
Logger::set(optList.at(i));
Logger::info("Logger set to " + optList.at(i));
}
else if (is_in(option, "proc_sorting", "cpu_sensor") or option.starts_with("graph_symbol") or option.starts_with("cpu_graph_"))
screen_redraw = true;
}
else
retval = NoChange;
}
else {
retval = NoChange;
}
//? Draw the menu
if (retval == Changed) {
Config::unlock();
auto& out = Global::overlay;
out = bg;
item_height = min((int)categories[selected_cat].size(), (int)floor((double)(height - 4) / 2));
pages = ceil((double)categories[selected_cat].size() / item_height);
if (page > pages - 1) page = pages - 1;
select_max = min(item_height - 1, (int)categories[selected_cat].size() - 1 - item_height * page);
if (selected > select_max) {
selected = select_max;
}
//? Get variable properties for currently selected option
if (selPred.none() or last_sel != (selected_cat << 8) + selected) {
selPred.reset();
last_sel = (selected_cat << 8) + selected;
const auto& selOption = categories[selected_cat][item_height * page + selected][0];
if (Config::ints.contains(selOption))
selPred.set(isInt);
else if (Config::bools.contains(selOption))
selPred.set(isBool);
else
selPred.set(isString);
if (not selPred.test(isString))
selPred.set(is2D);
else if (optionsList.contains(selOption)) {
selPred.set(isBrowseable);
}
if (not selPred.test(isBrowseable) and (selPred.test(isString) or selPred.test(isInt)))
selPred.set(isEditable);
}
//? Category buttons
out += Mv::to(y+7, x+4);
for (int i = 0; const auto& m : {"general", "cpu", "mem", "net", "proc"}) {
out += Fx::b + (i == selected_cat
? Theme::c("hi_fg") + '[' + Theme::c("title") + m + Theme::c("hi_fg") + ']'
: Theme::c("hi_fg") + to_string(i + 1) + Theme::c("title") + m + ' ')
+ Mv::r(10);
if (string button_name = "select_cat_" + to_string(i + 1); not editing and not mouse_mappings.contains(button_name))
mouse_mappings[button_name] = {y+6, x+2 + 15*i, 3, 15};
i++;
}
if (pages > 1) {
out += Mv::to(y+6 + height - 1, x+2) + Theme::c("hi_fg") + Symbols::title_left_down + Fx::b + Symbols::up + Theme::c("title") + " page "
+ to_string(page+1) + '/' + to_string(pages) + ' ' + Theme::c("hi_fg") + Symbols::down + Fx::ub + Symbols::title_right_down;
}
//? Option name and value
auto cy = y+9;
for (int c = 0, i = max(0, item_height * page); c++ < item_height and i < (int)categories[selected_cat].size(); i++) {
const auto& option = categories[selected_cat][i][0];
const auto& value = (option == "color_theme" ? (string) fs::path(Config::getS("color_theme")).stem() : Config::getAsString(option));
out += Mv::to(cy++, x + 1) + (c-1 == selected ? Theme::c("selected_bg") + Theme::c("selected_fg") : Theme::c("title"))
+ Fx::b + cjust(capitalize(s_replace(option, "_", " "))
+ (c-1 == selected and selPred.test(isBrowseable)
? ' ' + to_string(v_index(optionsList.at(option).get(), (option == "color_theme" ? Config::getS("color_theme") : value)) + 1) + '/' + to_string(optionsList.at(option).get().size())
: ""), 29);
out += Mv::to(cy++, x + 1) + (c-1 == selected ? "" : Theme::c("main_fg")) + Fx::ub + " "
+ (c-1 == selected and editing ? cjust(editor(24), 34, true) : cjust(value, 25, true)) + " ";
if (c-1 == selected) {
if (not editing and (selPred.test(is2D) or selPred.test(isBrowseable))) {
out += Fx::b + Mv::to(cy-1, x+2) + Symbols::left + Mv::to(cy-1, x+28) + Symbols::right;
mouse_mappings["left"] = {cy-2, x, 2, 5};
mouse_mappings["right"] = {cy-2, x+25, 2, 5};
}
if (selPred.test(isEditable)) {
out += Fx::b + Mv::to(cy-1, x+28 - (not editing and selPred.test(isInt) ? 2 : 0)) + (tty_mode ? "E" : Symbols::enter);
}
//? Description of selected option
out += Fx::reset + Theme::c("title") + Fx::b;
for (int cyy = y+7; const auto& desc : categories[selected_cat][i]) {
if (cyy++ == y+7) continue;
else if (cyy == y+10) out += Theme::c("main_fg") + Fx::ub;
else if (cyy > y + height + 4) break;
out += Mv::to(cyy, x+32) + desc;
}
}
}
if (not warnings.empty()) {
messageBox = msgBox{min(78, (int)ulen(warnings) + 10), msgBox::BoxTypes::OK, {uresize(warnings, 74)}, "warning"};
out += messageBox();
}
out += Fx::reset;
}
if (theme_refresh) {
Theme::setTheme();
Draw::banner_gen(0, 0, false, true);
screen_redraw = true;
redraw = true;
optionsMenu("");
}
if (screen_redraw) {
auto overlay_bkp = move(Global::overlay);
auto clock_bkp = move(Global::clock);
Draw::calcSizes();
Global::overlay = move(overlay_bkp);
Global::clock = move(clock_bkp);
recollect = true;
}
if (recollect) {
Runner::run("all", false, true);
retval = NoChange;
}
return (redraw ? Changed : retval);
}
int helpMenu(const string& key) {
static int y = 0, x = 0, height = 0, page = 0, pages = 0;
if (bg.empty()) page = 0;
int retval = Changed;
if (redraw) {
y = max(1, Term::height/2 - 4 - (int)(help_text.size() / 2));
x = Term::width/2 - 39;
height = min(Term::height - 6, (int)help_text.size() + 3);
pages = ceil((double)help_text.size() / (height - 3));
page = 0;
bg = Draw::banner_gen(y, 0, true);
bg += Draw::createBox(x, y + 6, 78, height, Theme::c("hi_fg"), true, "help");
}
else if (is_in(key, "escape", "q", "h", "backspace", "space", "enter", "mouse_click")) {
return Closed;
}
else if (pages > 1 and is_in(key, "down", "page_down", "tab", "mouse_scroll_down")) {
if (++page >= pages) page = 0;
}
else if (pages > 1 and is_in(key, "up", "page_up", "shift_tab", "mouse_scroll_up")) {
if (--page < 0) page = pages - 1;
}
else {
retval = NoChange;
}
if (retval == Changed) {
auto& out = Global::overlay;
out = bg;
if (pages > 1) {
out += Mv::to(y+height+6, x + 2) + Theme::c("hi_fg") + Symbols::title_left_down + Fx::b + Symbols::up + Theme::c("title") + " page "
+ to_string(page+1) + '/' + to_string(pages) + ' ' + Theme::c("hi_fg") + Symbols::down + Fx::ub + Symbols::title_right_down;
}
auto cy = y+7;
out += Mv::to(cy++, x + 1) + Theme::c("title") + Fx::b + cjust("Key:", 20) + "Description:";
for (int c = 0, i = max(0, (height - 3) * page); c++ < height - 3 and i < (int)help_text.size(); i++) {
out += Mv::to(cy++, x + 1) + Theme::c("hi_fg") + Fx::b + cjust(help_text[i][0], 20)
+ Theme::c("main_fg") + Fx::ub + help_text[i][1];
}
out += Fx::reset;
}
return (redraw ? Changed : retval);
}
//* Add menus here and update enum Menus in header
const auto menuFunc = vector{
ref(sizeError),
ref(signalChoose),
ref(signalSend),
ref(signalReturn),
ref(optionsMenu),
ref(helpMenu),
ref(mainMenu),
};
bitset<8> menuMask;
void process(string key) {
if (menuMask.none()) {
Menu::active = false;
Global::overlay.clear();
Global::overlay.shrink_to_fit();
Runner::pause_output = false;
bg.clear();
bg.shrink_to_fit();
currentMenu = -1;
Runner::run("all", true, true);
mouse_mappings.clear();
return;
}
if (currentMenu < 0 or not menuMask.test(currentMenu)) {
Menu::active = true;
redraw = true;
if (((menuMask.test(Main) or menuMask.test(Options) or menuMask.test(Help) or menuMask.test(SignalChoose))
and (Term::width < 80 or Term::height < 24))
or (Term::width < 50 or Term::height < 20)) {
menuMask.reset();
menuMask.set(SizeError);
}
for (const auto& i : iota(0, (int)menuMask.size())) {
if (menuMask.test(i)) currentMenu = i;
}
}
auto retCode = menuFunc.at(currentMenu)(key);
if (retCode == Closed) {
menuMask.reset(currentMenu);
mouse_mappings.clear();
bg.clear();
Runner::pause_output = false;
process();
}
else if (redraw) {
redraw = false;
Runner::run("all", true, true);
}
else if (retCode == Changed)
Runner::run("overlay");
else if (retCode == Switch) {
Runner::pause_output = false;
bg.clear();
redraw = true;
mouse_mappings.clear();
process();
}
}
void show(int menu, int signal) {
menuMask.set(menu);
signalToSend = signal;
process();
}
}