2022-08-30 17:54:49 +02:00
|
|
|
|
#!/usr/bin/env php
|
|
|
|
|
<?php
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
/**
|
|
|
|
|
* h-m-m
|
|
|
|
|
*
|
2023-02-05 08:23:29 +01:00
|
|
|
|
* h-m-m (pronounced like the interjection "hmm") is a simple, fast,
|
|
|
|
|
* keyboard-centric terminal-based tool for working with mind maps.
|
2022-09-19 20:33:27 +02:00
|
|
|
|
*
|
|
|
|
|
* @author Nader K. Rad <me@nader.pm>
|
|
|
|
|
* @link https://github.com/nadrad/h-m-m
|
|
|
|
|
* @license https://www.gnu.org/licenses/gpl-3.0.en.html GPLv3
|
|
|
|
|
*/
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:27:37 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// {{{ settings and defaults
|
2022-09-18 13:27:37 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mb_internal_encoding("UTF-8");
|
2022-09-18 13:27:37 +02:00
|
|
|
|
|
2022-09-16 02:50:35 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// $mm, short for "mind map", is an array that contains the
|
|
|
|
|
// 'nodes' array, as well as the other settings and parameters
|
|
|
|
|
// required for building and showing a mind map.
|
|
|
|
|
//
|
|
|
|
|
// escape codes for colors:
|
|
|
|
|
// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
2022-09-15 19:50:55 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm=[];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// parsing the command line arguments
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['arguments'] = [];
|
2023-10-20 09:57:33 +02:00
|
|
|
|
$mm['config'] = [];
|
|
|
|
|
$mm['env'] = [];
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$alen = count($argv);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
for ( $i = 1 ; $i < $alen ; $i++ )
|
|
|
|
|
if (substr($argv[$i],0,2) == '--')
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$a = explode('=', substr($argv[$i],2));
|
2022-09-26 17:09:45 +02:00
|
|
|
|
$mm['arguments'][ str_replace('-','_',$a[0]) ] = trim( $a[1] ?? true, '"' );
|
2022-09-19 20:33:27 +02:00
|
|
|
|
}
|
|
|
|
|
elseif (isset($mm['arguments']['filename']))
|
|
|
|
|
{
|
2022-09-20 20:49:23 +02:00
|
|
|
|
echo "Invalid arguments: more than one filename!".PHP_EOL;
|
2022-09-19 20:33:27 +02:00
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
$mm['arguments']['filename'] = $argv[$i];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// parsing the config file
|
2022-09-16 19:33:55 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$conf =
|
|
|
|
|
$mm['arguments']['config']
|
|
|
|
|
??
|
|
|
|
|
(
|
|
|
|
|
PHP_OS_FAMILY === 'Windows'
|
|
|
|
|
? $argv[0].'.conf'
|
|
|
|
|
:
|
|
|
|
|
(
|
|
|
|
|
PHP_OS_FAMILY === 'Darwin'
|
2022-09-19 20:53:38 +02:00
|
|
|
|
? getenv('HOME').'/Library/Preferences/h-m-m/h-m-m.conf'
|
|
|
|
|
: getenv('HOME').'/.config/h-m-m/h-m-m.conf'
|
2022-09-19 20:33:27 +02:00
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if (file_exists($conf))
|
|
|
|
|
{
|
|
|
|
|
$handle = fopen($conf, "r");
|
|
|
|
|
if ($handle)
|
|
|
|
|
{
|
|
|
|
|
while (($line = fgets($handle)) !== false)
|
|
|
|
|
{
|
|
|
|
|
if (empty(trim($line))) continue;
|
|
|
|
|
$c = explode('=',trim($line));
|
2022-09-19 20:53:38 +02:00
|
|
|
|
$mm['config'][ str_replace('-','_',trim($c[0] ?? 'NA')) ] = trim($c[1] ?? 'NA');
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
fclose($handle);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
2022-11-25 08:41:09 +01:00
|
|
|
|
elseif (isset($mm['arguments']['config']))
|
|
|
|
|
die("ERROR: the custom config file ($conf) doesn't exit!\n");
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// parsing the environment variables
|
|
|
|
|
|
|
|
|
|
$mm['env']=[];
|
|
|
|
|
$e = getenv();
|
|
|
|
|
foreach ($e as $k=>$v)
|
|
|
|
|
if (substr($k,0,4)=='hmm_')
|
2022-09-19 20:53:38 +02:00
|
|
|
|
$mm['env'][str_replace('-','_',substr($k,4))] = $v ?? '';
|
2022-09-19 20:33:27 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// and now, the settings!
|
|
|
|
|
// arguments > environment variables > config file > default
|
|
|
|
|
|
|
|
|
|
config($mm, 'max_parent_node_width', 25);
|
|
|
|
|
config($mm, 'max_leaf_node_width', 55);
|
|
|
|
|
config($mm, 'line_spacing', 1);
|
2023-03-15 09:09:17 +01:00
|
|
|
|
config($mm, 'align_levels', 0);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-15 09:24:48 +01:00
|
|
|
|
config($mm, 'symbol1', "✓");
|
|
|
|
|
config($mm, 'symbol2', "✗");
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
config($mm, 'show_hidden', 0);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
config($mm, 'initial_depth', 1);
|
|
|
|
|
config($mm, 'center_lock', false);
|
|
|
|
|
config($mm, 'focus_lock', false);
|
|
|
|
|
|
|
|
|
|
config($mm, 'max_undo_steps', 24);
|
|
|
|
|
|
|
|
|
|
config($mm, 'active_node_color', "\033[38;5;0m\033[48;5;172m\033[1m");
|
|
|
|
|
config($mm, 'message_color', "\033[38;5;0m\033[48;5;141m\033[1m");
|
|
|
|
|
config($mm, 'doubt_color', "\033[38;5;168m");
|
|
|
|
|
|
2022-09-29 10:14:11 +02:00
|
|
|
|
config($mm, 'post_export_command', "");
|
|
|
|
|
|
2022-09-26 17:09:45 +02:00
|
|
|
|
config($mm, 'clipboard', "os");
|
|
|
|
|
config($mm, 'clipboard_file', "/tmp/h-m-m");
|
|
|
|
|
config($mm, 'clipboard_in_command', "");
|
|
|
|
|
config($mm, 'clipboard_out_command', "");
|
|
|
|
|
|
2023-07-23 11:22:48 +02:00
|
|
|
|
config($mm, 'auto_save', false);
|
2023-07-25 09:09:07 +02:00
|
|
|
|
config($mm, 'echo_keys', false);
|
2023-07-23 11:22:48 +02:00
|
|
|
|
|
2022-11-25 13:38:07 +01:00
|
|
|
|
|
|
|
|
|
if (isset($mm['arguments']['debug_config']))
|
|
|
|
|
{
|
|
|
|
|
echo "1. the config arguments:\n";
|
|
|
|
|
print_r($mm['arguments']);
|
|
|
|
|
echo "2. the environment variables:\n";
|
|
|
|
|
print_r($mm['env']);
|
|
|
|
|
echo "3. the config file:\n";
|
|
|
|
|
print_r($mm['config']);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-26 17:09:45 +02:00
|
|
|
|
$clipboard = '';
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
|
2023-02-05 18:22:33 +01:00
|
|
|
|
$mm['show_logo'] = true;
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['changes'] = [];
|
|
|
|
|
$mm['change_active_node'] = [];
|
|
|
|
|
$mm['change_index'] = 0;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
$mm['top_left_column'] = 0;
|
|
|
|
|
$mm['top_left_row'] = 0;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['terminal_width'] = (int)exec('tput cols');
|
|
|
|
|
$mm['terminal_height'] = (int)exec('tput lines');
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['viewport_left'] = 0;
|
|
|
|
|
$mm['viewport_top'] = 0;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['root_id'] = 2;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
const min_indentation = 2;
|
|
|
|
|
const width_tolerance = 1.3;
|
|
|
|
|
const width_min = 15;
|
|
|
|
|
const width_change_factor = 1.2;
|
|
|
|
|
const max_width_padding = 30;
|
2022-09-19 20:33:27 +02:00
|
|
|
|
const left_padding = 1;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
const conn_left_len = 6;
|
|
|
|
|
const conn_right_len = 4;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
$mm['conn_right'] = str_repeat('─', conn_right_len - 2 );
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$mm['conn_left'] = str_repeat('─', conn_left_len -2 );
|
|
|
|
|
$mm['conn_single'] = str_repeat('─', conn_left_len + conn_right_len - 3 );
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
const vertical_offset = 4;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
const BOM = "\xEF\xBB\xBF";
|
|
|
|
|
const default_color = "\033[0m";
|
|
|
|
|
const clear_screen = "\033[2J";
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
const special_keys =
|
|
|
|
|
[
|
|
|
|
|
'ctrl_a' => "\001",
|
|
|
|
|
'ctrl_b' => "\002",
|
|
|
|
|
'ctrl_c' => "\003",
|
|
|
|
|
'ctrl_d' => "\004",
|
|
|
|
|
'ctrl_e' => "\005",
|
|
|
|
|
'ctrl_f' => "\006",
|
|
|
|
|
'ctrl_g' => "\007",
|
2023-07-23 11:09:17 +02:00
|
|
|
|
'ctrl_back_space' => "\010",
|
2023-07-23 10:45:10 +02:00
|
|
|
|
'ctrl_h' => "\010",
|
|
|
|
|
'ctrl_i' => "\011",
|
|
|
|
|
'ctrl_j' => "\012",
|
|
|
|
|
'ctrl_k' => "\013",
|
|
|
|
|
'ctrl_l' => "\014",
|
|
|
|
|
'ctrl_m' => "\015",
|
|
|
|
|
'ctrl_n' => "\016",
|
|
|
|
|
'ctrl_o' => "\017",
|
|
|
|
|
'ctrl_p' => "\020",
|
|
|
|
|
'ctrl_q' => "\021",
|
|
|
|
|
'ctrl_r' => "\022",
|
|
|
|
|
'ctrl_s' => "\023",
|
|
|
|
|
'ctrl_t' => "\024",
|
|
|
|
|
'ctrl_u' => "\025",
|
|
|
|
|
'ctrl_v' => "\026",
|
|
|
|
|
'ctrl_w' => "\027",
|
|
|
|
|
'ctrl_x' => "\030",
|
|
|
|
|
'ctrl_y' => "\031",
|
|
|
|
|
'ctrl_z' => "\032",
|
|
|
|
|
|
|
|
|
|
'alt_a' => "\033\141",
|
|
|
|
|
'alt_b' => "\033\142",
|
|
|
|
|
'alt_c' => "\033\143",
|
|
|
|
|
'alt_d' => "\033\144",
|
|
|
|
|
'alt_e' => "\033\145",
|
|
|
|
|
'alt_f' => "\033\146",
|
|
|
|
|
'alt_g' => "\033\147",
|
|
|
|
|
'alt_h' => "\033\150",
|
|
|
|
|
'alt_i' => "\033\151",
|
|
|
|
|
'alt_j' => "\033\152",
|
|
|
|
|
'alt_k' => "\033\153",
|
|
|
|
|
'alt_l' => "\033\154",
|
|
|
|
|
'alt_m' => "\033\155",
|
|
|
|
|
'alt_n' => "\033\156",
|
|
|
|
|
'alt_o' => "\033\157",
|
|
|
|
|
'alt_p' => "\033\160",
|
|
|
|
|
'alt_q' => "\033\161",
|
|
|
|
|
'alt_r' => "\033\162",
|
|
|
|
|
'alt_s' => "\033\163",
|
|
|
|
|
'alt_t' => "\033\164",
|
|
|
|
|
'alt_u' => "\033\165",
|
|
|
|
|
'alt_v' => "\033\166",
|
|
|
|
|
'alt_w' => "\033\167",
|
|
|
|
|
'alt_x' => "\033\170",
|
|
|
|
|
'alt_y' => "\033\171",
|
|
|
|
|
'alt_z' => "\033\172",
|
|
|
|
|
|
|
|
|
|
'arr_down' => "\033\133\102",
|
|
|
|
|
'arr_right'=> "\033\133\103",
|
|
|
|
|
'arr_up' => "\033\133\101",
|
|
|
|
|
'arr_left' => "\033\133\104",
|
|
|
|
|
|
|
|
|
|
'ctrl_arr_left' => "\033\133\061\073\065\104",
|
|
|
|
|
'shift_arr_left' => "\033\133\061\073\062\104",
|
|
|
|
|
|
|
|
|
|
'ctrl_arr_right' => "\033\133\061\073\065\103",
|
|
|
|
|
'shift_arr_right' => "\033\133\061\073\062\103",
|
|
|
|
|
|
|
|
|
|
'home' => "\033\133\110",
|
|
|
|
|
'end' => "\033\133\106",
|
|
|
|
|
|
2023-07-25 12:00:09 +02:00
|
|
|
|
'home_alternative' => "\033\133\061\176",
|
|
|
|
|
'end_alternative' => "\033\133\064\176",
|
2023-07-25 09:17:21 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
'del' => "\033\133\063\176",
|
|
|
|
|
'ctrl_del' => "\033\133\63\073\065\176",
|
|
|
|
|
'back_space' => "\177",
|
|
|
|
|
|
|
|
|
|
'enter' => "\012",
|
|
|
|
|
'space' => "\040",
|
|
|
|
|
'tab' => "\011",
|
|
|
|
|
'esc' => "\033",
|
|
|
|
|
'equal' => "="
|
|
|
|
|
|
|
|
|
|
];
|
2022-09-16 21:03:12 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
const reset_page = "\033[2J\033[0;0f";
|
|
|
|
|
const reset_color = "\033[0m";
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
const invert_on = "\033[7m";
|
|
|
|
|
const invert_off = "\033[27m";
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
const dim_on = "\033[2m";
|
|
|
|
|
const dim_off = "\033[22m";
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
const line_on = "\033[0m\033[38;5;95m";
|
|
|
|
|
const line_off = "\033[0m";
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-18 13:39:49 +02:00
|
|
|
|
const collapsed_symbol_on = "\033[38;5;215m";
|
|
|
|
|
const collapsed_symbol_off = "\033[0m";
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
const insert_sibling = 0;
|
|
|
|
|
const insert_child = 1;
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
$keybindings = [];
|
|
|
|
|
|
|
|
|
|
$keybindings['a'] = 'edit_node_append';
|
|
|
|
|
$keybindings['A'] = 'edit_node_replace';
|
|
|
|
|
|
|
|
|
|
$keybindings['b'] = 'expand_all';
|
|
|
|
|
|
|
|
|
|
$keybindings['c'] = 'center_active_node';
|
|
|
|
|
$keybindings['C'] = 'toggle_center_lock';
|
|
|
|
|
$keybindings[special_keys['ctrl_c']] = 'quit';
|
|
|
|
|
|
|
|
|
|
$keybindings['d'] = 'delete_node';
|
|
|
|
|
$keybindings['D'] = 'delete_children';
|
|
|
|
|
$keybindings[special_keys['del']] = 'delete_node_without_clipboard';
|
|
|
|
|
|
|
|
|
|
$keybindings['e'] = 'edit_node_append';
|
|
|
|
|
$keybindings['E'] = 'edit_node_replace';
|
|
|
|
|
|
|
|
|
|
$keybindings['f'] = 'focus';
|
|
|
|
|
$keybindings['F'] = 'toggle_focus_lock';
|
|
|
|
|
|
|
|
|
|
$keybindings['g'] = 'go_to_top';
|
|
|
|
|
$keybindings['G'] = 'go_to_bottom';
|
|
|
|
|
|
|
|
|
|
$keybindings['h'] = 'go_left';
|
|
|
|
|
$keybindings['H'] = 'toggle_hide';
|
|
|
|
|
$keybindings[special_keys['ctrl_h']] = 'toggle_show_hidden';
|
|
|
|
|
|
|
|
|
|
$keybindings['i'] = 'edit_node_append';
|
|
|
|
|
$keybindings['I'] = 'edit_node_replace';
|
|
|
|
|
|
|
|
|
|
$keybindings['j'] = 'go_down';
|
|
|
|
|
$keybindings['J'] = 'move_node_down';
|
|
|
|
|
|
|
|
|
|
$keybindings['k'] = 'go_up';
|
|
|
|
|
$keybindings['K'] = 'move_node_up';
|
|
|
|
|
|
|
|
|
|
$keybindings['l'] = 'go_right';
|
|
|
|
|
|
|
|
|
|
$keybindings['m'] = 'go_to_root';
|
|
|
|
|
$keybindings['~'] = 'go_to_root';
|
|
|
|
|
|
|
|
|
|
$keybindings['n'] = 'next_search_result';
|
|
|
|
|
$keybindings['N'] = 'previous_search_result';
|
|
|
|
|
|
|
|
|
|
$keybindings['o'] = 'insert_new_sibling';
|
|
|
|
|
$keybindings['O'] = 'insert_new_child';
|
|
|
|
|
$keybindings[special_keys['ctrl_o']] = 'open_link';
|
|
|
|
|
|
|
|
|
|
$keybindings['p'] = 'paste_as_children';
|
|
|
|
|
$keybindings['P'] = 'paste_as_siblings';
|
|
|
|
|
$keybindings[special_keys['ctrl_p']] = 'append';
|
|
|
|
|
|
|
|
|
|
$keybindings['q'] = 'quit';
|
|
|
|
|
$keybindings['Q'] = 'shutdown';
|
2024-03-30 19:06:41 +01:00
|
|
|
|
$keybindings[special_keys['ctrl_q']] = 'quit_with_debug';
|
2023-07-23 10:45:10 +02:00
|
|
|
|
|
|
|
|
|
$keybindings['r'] = 'collapse_other_branches';
|
|
|
|
|
$keybindings['R'] = 'collapse_inner';
|
|
|
|
|
|
|
|
|
|
$keybindings['s'] = 'save';
|
|
|
|
|
$keybindings['S'] = 'save_as';
|
|
|
|
|
|
|
|
|
|
$keybindings['t'] = 'toggle_symbol';
|
|
|
|
|
$keybindings['T'] = 'sort_siblings';
|
|
|
|
|
$keybindings['#'] = 'toggle_numbers';
|
|
|
|
|
|
|
|
|
|
$keybindings['u'] = 'undo';
|
|
|
|
|
|
|
|
|
|
$keybindings['v'] = 'collapse_all';
|
|
|
|
|
$keybindings['V'] = 'collapse_children';
|
|
|
|
|
|
|
|
|
|
$keybindings['w'] = 'increase_text_width';
|
|
|
|
|
$keybindings['W'] = 'decrease_text_width';
|
|
|
|
|
|
|
|
|
|
$keybindings['x'] = 'export_html';
|
|
|
|
|
$keybindings['X'] = 'export_text';
|
|
|
|
|
|
|
|
|
|
$keybindings['y'] = 'yank_node';
|
|
|
|
|
$keybindings['Y'] = 'yank_children';
|
|
|
|
|
|
|
|
|
|
$keybindings['z'] = 'decrease_line_spacing';
|
|
|
|
|
$keybindings['Z'] = 'increase_line_spacing';
|
|
|
|
|
|
|
|
|
|
$keybindings["\n"] = 'insert_new_sibling';
|
|
|
|
|
$keybindings["\t"] = 'insert_new_child';
|
|
|
|
|
$keybindings[" "] = 'toggle_node';
|
|
|
|
|
|
|
|
|
|
$keybindings[special_keys['arr_down']] = 'go_down';
|
|
|
|
|
$keybindings[special_keys['arr_up']] = 'go_up';
|
|
|
|
|
$keybindings[special_keys['arr_right']] = 'go_right';
|
|
|
|
|
$keybindings[special_keys['arr_left']] = 'go_left';
|
|
|
|
|
|
|
|
|
|
$keybindings['1'] = 'collapse_level_1';
|
|
|
|
|
$keybindings['2'] = 'collapse_level_2';
|
|
|
|
|
$keybindings['3'] = 'collapse_level_3';
|
|
|
|
|
$keybindings['4'] = 'collapse_level_4';
|
|
|
|
|
$keybindings['5'] = 'collapse_level_5';
|
|
|
|
|
$keybindings['6'] = 'collapse_level_6';
|
|
|
|
|
$keybindings['7'] = 'collapse_level_7';
|
|
|
|
|
$keybindings['8'] = 'collapse_level_8';
|
|
|
|
|
$keybindings['9'] = 'collapse_level_9';
|
|
|
|
|
|
|
|
|
|
$keybindings['|'] = 'toggle_align';
|
|
|
|
|
|
2023-07-23 11:09:17 +02:00
|
|
|
|
$keybindings['?'] = 'help';
|
2023-07-23 10:45:10 +02:00
|
|
|
|
$keybindings['/'] = 'search';
|
|
|
|
|
$keybindings[special_keys['ctrl_f']] = 'search';
|
|
|
|
|
|
|
|
|
|
$keybindings['='] = 'increase_positive_rank';
|
|
|
|
|
$keybindings['+'] = 'decrease_positive_rank';
|
|
|
|
|
$keybindings['-'] = 'increase_negative_rank';
|
|
|
|
|
$keybindings['_'] = 'decrease_negative_rank';
|
|
|
|
|
|
|
|
|
|
foreach ($mm['config'] as $key=>$value)
|
|
|
|
|
if (substr($key,0,4) == 'bind')
|
|
|
|
|
{
|
|
|
|
|
$key = trim(substr($key,4));
|
|
|
|
|
if (isset(special_keys[$key]))
|
|
|
|
|
$key = special_keys[$key];
|
|
|
|
|
if (!is_callable($value))
|
|
|
|
|
{
|
|
|
|
|
echo 'Config error! "'.$value.'" is an unknown command.'."\n";
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
$keybindings[$key] = trim($value);
|
|
|
|
|
}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
|
2022-11-08 13:44:15 +01:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function config(&$mm, $key, $default)
|
|
|
|
|
{
|
|
|
|
|
$mm[$key] =
|
2022-11-25 14:03:22 +01:00
|
|
|
|
str_replace
|
|
|
|
|
(
|
|
|
|
|
'\033'
|
|
|
|
|
,"\033"
|
|
|
|
|
,
|
|
|
|
|
$mm['arguments'][$key]
|
|
|
|
|
?? $mm['env'][$key]
|
|
|
|
|
?? $mm['config'][$key]
|
|
|
|
|
?? $default
|
|
|
|
|
);
|
2022-09-19 20:33:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
|
|
|
|
// }}}
|
2022-09-15 09:51:32 +02:00
|
|
|
|
// {{{ checking the requirements
|
2022-09-14 22:25:16 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function check_required_extensions()
|
2022-09-14 22:25:16 +02:00
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if (!function_exists('mb_strlen'))
|
2022-09-14 22:25:16 +02:00
|
|
|
|
{
|
2022-09-20 20:49:23 +02:00
|
|
|
|
echo 'Required extension mbstring is not enabled; please check your php installation!'.PHP_EOL;
|
2022-09-19 20:33:27 +02:00
|
|
|
|
exit(1);
|
2022-09-14 22:25:16 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-15 09:51:32 +02:00
|
|
|
|
|
|
|
|
|
function check_the_available_clipboard_tool(&$mm)
|
|
|
|
|
{
|
2022-09-26 17:09:45 +02:00
|
|
|
|
|
|
|
|
|
if ($mm['clipboard'] == 'file' && !file_exists($mm['clipboard_file']))
|
|
|
|
|
file_put_contents($mm['clipboard_file'],'');
|
|
|
|
|
|
|
|
|
|
if ($mm['clipboard'] != 'os')
|
|
|
|
|
return;
|
|
|
|
|
|
2022-09-15 09:51:32 +02:00
|
|
|
|
if (PHP_OS_FAMILY === "Windows")
|
|
|
|
|
{
|
2022-09-26 17:09:45 +02:00
|
|
|
|
$mm['os_clipboard']['write'] = "clip";
|
|
|
|
|
$mm['os_clipboard']['read'] = 'powershell -sta "add-type -as System.Windows.Forms; [windows.forms.clipboard]::GetText()"';
|
2022-09-15 09:51:32 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if (PHP_OS_FAMILY === "Darwin")
|
2022-09-15 09:51:32 +02:00
|
|
|
|
{
|
2022-09-26 17:09:45 +02:00
|
|
|
|
$mm['os_clipboard']['write'] = "pbcopy";
|
|
|
|
|
$mm['os_clipboard']['read'] = 'pbpaste';
|
2022-09-15 09:51:32 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// now, the main OS ;)
|
|
|
|
|
|
2023-12-04 06:43:00 +01:00
|
|
|
|
exec('command -v xclip xsel wl-copy klipper', $result);
|
2022-09-15 09:51:32 +02:00
|
|
|
|
$tool = basename($result[0] ?? '');
|
|
|
|
|
|
|
|
|
|
if (trim($tool)==='')
|
|
|
|
|
{
|
2023-12-04 06:43:00 +01:00
|
|
|
|
echo "Can't find your clipboard tool! I expected to find xclip, xsel, wl-clipboard, or Klipper.".PHP_EOL;
|
2022-09-20 20:29:25 +02:00
|
|
|
|
exit(1);
|
2022-09-15 09:51:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch ($tool)
|
|
|
|
|
{
|
|
|
|
|
case 'xclip':
|
2022-09-26 17:09:45 +02:00
|
|
|
|
$mm['os_clipboard']['write'] = 'xclip -selection clipboard';
|
|
|
|
|
$mm['os_clipboard']['read'] = 'xclip -out -selection clipboard';
|
2022-09-15 09:51:32 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'xsel':
|
2022-09-26 17:09:45 +02:00
|
|
|
|
$mm['os_clipboard']['write'] = 'xsel --clipboard';
|
|
|
|
|
$mm['os_clipboard']['read'] = 'xsel --clipboard';
|
2022-09-15 09:51:32 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'wl-copy':
|
2022-09-26 17:09:45 +02:00
|
|
|
|
$mm['os_clipboard']['write'] = 'wl-copy';
|
|
|
|
|
$mm['os_clipboard']['read'] = 'wl-paste';
|
2022-09-15 09:51:32 +02:00
|
|
|
|
break;
|
|
|
|
|
|
2023-12-04 06:43:00 +01:00
|
|
|
|
case 'klipper':
|
|
|
|
|
$mm['clipboard'] = 'command';
|
|
|
|
|
$mm['clipboard_in_command'] = 'qdbus org.kde.klipper /klipper setClipboardContents %text%';
|
|
|
|
|
$mm['clipboard_out_command'] = 'qdbus org.kde.klipper /klipper getClipboardContents';
|
|
|
|
|
break;
|
|
|
|
|
|
2022-09-15 09:51:32 +02:00
|
|
|
|
default:
|
2022-09-20 20:49:23 +02:00
|
|
|
|
echo "I can't find your clipboard tool!".PHP_EOL;
|
2022-09-20 20:29:25 +02:00
|
|
|
|
exit(1);
|
2022-09-15 09:51:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-14 22:25:16 +02:00
|
|
|
|
// }}}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// {{{ alternative screen buffer
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function enable_alternate_screen()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
// https://www.ibm.com/docs/en/aix/7.1?topic=s-stty-command
|
2022-09-19 20:33:27 +02:00
|
|
|
|
system('stty cbreak -echo -crterase intr undef');
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2024-04-08 08:26:55 +02:00
|
|
|
|
echo
|
2022-09-19 20:33:27 +02:00
|
|
|
|
"\033[?1049h" // enabling the alternate screen buffer
|
|
|
|
|
."\033[?25l" // disabling the text cursor
|
|
|
|
|
."\033[?9;1000;1001;1002;1003;1004;1007;1005;1006;1015;1016l" // disabling the mouse
|
|
|
|
|
.clear_screen
|
|
|
|
|
;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function shutdown()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2024-04-08 08:26:55 +02:00
|
|
|
|
echo
|
2022-09-19 20:33:27 +02:00
|
|
|
|
clear_screen
|
|
|
|
|
."\033[?1049l" // enabling the default screen buffer
|
|
|
|
|
."\033[?25h" // enabling the text cursor
|
|
|
|
|
;
|
|
|
|
|
system("stty sane");
|
2023-02-07 20:21:56 +01:00
|
|
|
|
change_window_title('');
|
2022-09-19 20:33:27 +02:00
|
|
|
|
exit;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// {{{ list to map converter
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function list_to_map($lines, $root_id, $start_id)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
// calculating the indentation shift and cleaning up the special characters
|
2022-09-15 19:50:55 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$indentation_shift = 9999999;
|
2022-09-15 19:50:55 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($lines as $lid=>$line)
|
|
|
|
|
{
|
|
|
|
|
$lines[$lid] =
|
2022-09-16 14:31:09 +02:00
|
|
|
|
mb_ereg_replace
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
2023-07-02 16:27:30 +02:00
|
|
|
|
"^( *)•"
|
|
|
|
|
,'\1*'
|
|
|
|
|
,
|
|
|
|
|
mb_ereg_replace
|
2022-09-16 14:31:09 +02:00
|
|
|
|
(
|
2023-07-02 16:27:30 +02:00
|
|
|
|
"[\000-\010\013-\037\177]|".BOM
|
|
|
|
|
,''
|
|
|
|
|
,str_replace
|
|
|
|
|
(
|
|
|
|
|
[ "\t", "\n" ]
|
|
|
|
|
,[ " ", " " ]
|
|
|
|
|
,$lines[$lid]
|
|
|
|
|
)
|
2022-09-16 14:31:09 +02:00
|
|
|
|
)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$indentation = mb_strlen($lines[$lid]) - mb_strlen(ltrim($lines[$lid]));
|
|
|
|
|
$start = mb_substr($lines[$lid], $indentation, 2);
|
|
|
|
|
|
|
|
|
|
if ($start=='* ' || $start=='- ')
|
|
|
|
|
{
|
|
|
|
|
$lines[$lid][$indentation] = ' ';
|
|
|
|
|
$indentation += 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (trim($lines[$lid])!='')
|
|
|
|
|
$indentation_shift =
|
|
|
|
|
min
|
|
|
|
|
(
|
|
|
|
|
$indentation_shift
|
|
|
|
|
,$indentation
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// building the tree
|
|
|
|
|
|
|
|
|
|
$nodes = [];
|
|
|
|
|
$id = $start_id;
|
|
|
|
|
|
|
|
|
|
$previous_level = 1;
|
|
|
|
|
$level = 1;
|
|
|
|
|
$previous_indentation = 0;
|
|
|
|
|
|
|
|
|
|
$level_parent[1] = $root_id;
|
|
|
|
|
$level_indentation[1] = 0;
|
|
|
|
|
|
|
|
|
|
foreach ($lines as $line)
|
|
|
|
|
if (trim($line)!='')
|
|
|
|
|
{
|
|
|
|
|
// warming up for this round!
|
|
|
|
|
$indentation = mb_strlen($line) - mb_strlen(ltrim($line)) - $indentation_shift;
|
|
|
|
|
|
|
|
|
|
// going one level down
|
|
|
|
|
if ($indentation > $previous_indentation )
|
|
|
|
|
{
|
|
|
|
|
$level = $previous_level + 1;
|
|
|
|
|
$level_indentation[$level] = $indentation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// going one or more levels up
|
|
|
|
|
if ($indentation < $previous_indentation )
|
|
|
|
|
foreach ($level_indentation as $plevel=>$pindentation)
|
|
|
|
|
if ($pindentation == $indentation)
|
|
|
|
|
$level = $plevel;
|
|
|
|
|
|
|
|
|
|
// saving the latest level_parent
|
|
|
|
|
if ($level > $previous_level)
|
|
|
|
|
$level_parent[$level] = $id-1;
|
|
|
|
|
|
|
|
|
|
// done! saving the data
|
|
|
|
|
|
|
|
|
|
$nodes[$id] =
|
|
|
|
|
[
|
|
|
|
|
'title' => trim($line)
|
|
|
|
|
,'parent' => $level_parent[$level]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// getting ready for the next round!
|
|
|
|
|
$previous_indentation = $indentation;
|
|
|
|
|
$previous_level = $level;
|
|
|
|
|
$id++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// setting a few properties that simplify future calculations
|
|
|
|
|
|
|
|
|
|
foreach ($nodes as $id=>$node)
|
|
|
|
|
{
|
|
|
|
|
$nodes[$id]['collapsed'] = false;
|
|
|
|
|
$nodes[$id]['is_leaf'] = true;
|
|
|
|
|
$nodes[$id]['children'] = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($nodes as $id=>$node)
|
|
|
|
|
if (isset($nodes[ $node['parent'] ]))
|
|
|
|
|
{
|
|
|
|
|
$nodes[ $node['parent'] ]['is_leaf'] = false;
|
|
|
|
|
$nodes[ $node['parent'] ]['children'][] = $id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return($nodes);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// {{{ map to list converter
|
|
|
|
|
|
|
|
|
|
function map_to_list(&$mm, $id, $exclude_parent = false, $base = 0)
|
|
|
|
|
{
|
|
|
|
|
if (!$exclude_parent)
|
2022-09-20 20:49:23 +02:00
|
|
|
|
$output = str_repeat("\t",$base).$mm['nodes'][$id]['title'].PHP_EOL;
|
2022-09-19 20:33:27 +02:00
|
|
|
|
else
|
|
|
|
|
$output = '';
|
|
|
|
|
|
|
|
|
|
foreach ($mm['nodes'][$id]['children'] as $cid)
|
|
|
|
|
$output .= map_to_list($mm, $cid, false, $base+1-$exclude_parent);
|
|
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ load file
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function load_file(&$mm)
|
|
|
|
|
{
|
2023-03-26 14:25:36 +02:00
|
|
|
|
$mm['filename'] = $mm['arguments']['filename'] ?? '';
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2023-03-26 14:25:36 +02:00
|
|
|
|
if (isset($mm['arguments']['filename']) && file_exists($mm['filename']))
|
|
|
|
|
$lines = file($mm['filename'], FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
2022-11-08 13:44:15 +01:00
|
|
|
|
else
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
load_empty_map($mm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// starting from 2 instead of 1, in case the files doesn't have
|
|
|
|
|
// a single root and we have to inject one. leaving "1" empty
|
|
|
|
|
// won't cause any problems.
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$new_nodes = list_to_map($lines, 0, 2);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2022-10-13 10:45:40 +02:00
|
|
|
|
if (empty($new_nodes))
|
|
|
|
|
{
|
|
|
|
|
load_empty_map($mm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2023-02-07 20:12:50 +01:00
|
|
|
|
change_window_title($mm['filename']);
|
|
|
|
|
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
// checking to see how many first-level nodes we have
|
|
|
|
|
$first_level_nodes = [];
|
|
|
|
|
foreach ($new_nodes as $id=>$node)
|
|
|
|
|
if ($id!=0 && $node['parent']==0)
|
|
|
|
|
$first_level_nodes[] = $id;
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][0]['parent'] = -1;
|
|
|
|
|
$mm['nodes'][0]['title'] = 'X';
|
|
|
|
|
$mm['nodes'][0]['is_leaf'] = false;
|
|
|
|
|
|
|
|
|
|
if (count($first_level_nodes)>1)
|
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['root_id'] = 1;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
$mm['nodes'][1]['parent'] = 0;
|
|
|
|
|
$mm['nodes'][1]['title'] = 'root';
|
|
|
|
|
$mm['nodes'][1]['is_leaf'] = false;
|
|
|
|
|
$mm['nodes'][1]['children'] = $first_level_nodes;
|
|
|
|
|
$mm['nodes'][0]['children'] = [1];
|
|
|
|
|
|
|
|
|
|
foreach ($new_nodes as $id=>$node)
|
|
|
|
|
if ($node['parent']==0)
|
|
|
|
|
$new_nodes[$id]['parent'] = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
$mm['nodes'][0]['children'] = $first_level_nodes;
|
|
|
|
|
|
|
|
|
|
$mm['nodes'] = $mm['nodes'] + $new_nodes;
|
|
|
|
|
|
|
|
|
|
if (isset($mm['nodes'][1]))
|
|
|
|
|
$mm['active_node']=1;
|
|
|
|
|
else
|
|
|
|
|
$mm['active_node']=2;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ list visible children
|
|
|
|
|
|
|
|
|
|
function list_visible_children(&$mm, $id)
|
|
|
|
|
{
|
|
|
|
|
$mm['nodes'][$id]['visible_children'] = [];
|
|
|
|
|
foreach ($mm['nodes'][$id]['children'] as $cid)
|
|
|
|
|
if (substr($mm['nodes'][$cid]['title'],0,9) != '[HIDDEN] ')
|
|
|
|
|
$mm['nodes'][$id]['visible_children'][] = $cid;
|
|
|
|
|
|
|
|
|
|
foreach ($mm['nodes'][$id]['children'] as $cid)
|
|
|
|
|
list_visible_children($mm, $cid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ calculate w, x, lh, and clh
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function calculate_x_and_lh(&$mm, $id)
|
|
|
|
|
{
|
|
|
|
|
$node = $mm['nodes'][$id];
|
|
|
|
|
|
2023-03-15 09:09:17 +01:00
|
|
|
|
$mm['nodes'][$id]['x'] =
|
|
|
|
|
$mm['nodes'][ $node['parent'] ]['x']
|
2022-09-04 19:05:06 +02:00
|
|
|
|
+ $mm['nodes'][ $node['parent'] ]['w']
|
|
|
|
|
+ conn_left_len
|
|
|
|
|
+ conn_right_len
|
|
|
|
|
+ 1
|
|
|
|
|
+
|
|
|
|
|
(
|
|
|
|
|
$node['parent']==0
|
|
|
|
|
? 1 - conn_right_len - conn_left_len
|
|
|
|
|
: 0
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$at_the_end =
|
|
|
|
|
$node['is_leaf']
|
|
|
|
|
|| ($node['collapsed'] ?? false)
|
|
|
|
|
|| count($node['visible_children']) == 0
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$max_width =
|
|
|
|
|
$at_the_end
|
|
|
|
|
? $mm['max_leaf_node_width']
|
|
|
|
|
: $mm['max_parent_node_width']
|
|
|
|
|
;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
if ( mb_strlen($node['title']) > width_tolerance * $max_width )
|
|
|
|
|
{
|
2022-09-20 20:49:23 +02:00
|
|
|
|
$lines = explode(PHP_EOL ,wordwrap($node['title'] ,$max_width, PHP_EOL));
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
$mm['nodes'][$id]['w'] = 0;
|
|
|
|
|
foreach ($lines as $line)
|
|
|
|
|
$mm['nodes'][$id]['w'] =
|
2024-04-04 10:55:44 +02:00
|
|
|
|
max($mm['nodes'][$id]['w'], trim(mb_strwidth($line)));
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
$mm['nodes'][$id]['lh'] = count($lines);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-04-04 10:55:44 +02:00
|
|
|
|
$mm['nodes'][$id]['w'] = mb_strwidth(trim($node['title']));
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][$id]['lh'] = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$mm['map_width'] =
|
|
|
|
|
max
|
|
|
|
|
(
|
|
|
|
|
$mm['map_width']
|
|
|
|
|
, $mm['nodes'][$id]['x']
|
|
|
|
|
+ $mm['nodes'][$id]['w']
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][$id]['clh'] = 0;
|
2023-03-17 20:04:49 +01:00
|
|
|
|
if ($at_the_end)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][$id]['clh'] = $mm['nodes'][$id]['lh'];
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($node['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
calculate_x_and_lh($mm, $cid);
|
|
|
|
|
$mm['nodes'][$id]['clh'] += $mm['nodes'][$cid]['clh'];
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-03-15 09:09:17 +01:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ calculate aligned x
|
|
|
|
|
|
|
|
|
|
function calculate_aligned_x(&$mm,$id,$x)
|
|
|
|
|
{
|
|
|
|
|
$mm['map_width'] =
|
|
|
|
|
max
|
|
|
|
|
(
|
|
|
|
|
$mm['map_width']
|
|
|
|
|
, $mm['nodes'][$id]['x']
|
|
|
|
|
+ $mm['nodes'][$id]['w']
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$max_width = 0;
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($mm['nodes'][$id]['visible_children'] as $cid)
|
2023-03-15 09:09:17 +01:00
|
|
|
|
{
|
|
|
|
|
$max_width = max( $max_width, $mm['nodes'][$cid]['w'] );
|
|
|
|
|
$mm['nodes'][$cid]['x'] = $x;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($mm['nodes'][$id]['visible_children'] as $cid)
|
2023-03-15 09:09:17 +01:00
|
|
|
|
calculate_aligned_x
|
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$cid
|
|
|
|
|
,$max_width
|
|
|
|
|
+$x
|
|
|
|
|
+conn_left_len
|
|
|
|
|
+conn_right_len
|
|
|
|
|
+1
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ calculate h
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function calculate_h(&$mm)
|
|
|
|
|
{
|
|
|
|
|
$unfinished = true;
|
|
|
|
|
while ($unfinished)
|
|
|
|
|
{
|
|
|
|
|
$unfinished = false;
|
|
|
|
|
|
|
|
|
|
foreach ($mm['nodes'] as $id=>$node)
|
|
|
|
|
|
2023-04-12 11:09:46 +02:00
|
|
|
|
if ($node['is_leaf'] || $node['visible_children']==0 || ($node['collapsed'] ?? false))
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['nodes'][$id]['h']
|
2022-09-04 19:05:06 +02:00
|
|
|
|
= $mm['line_spacing']
|
|
|
|
|
+ $mm['nodes'][$id]['lh']
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$h = 0;
|
|
|
|
|
$unready = false;
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($node['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($mm['nodes'][$cid]['h']>=0)
|
|
|
|
|
$h += $mm['nodes'][$cid]['h'];
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$unready = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($unready)
|
|
|
|
|
$unfinished = true;
|
|
|
|
|
else
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['nodes'][$id]['h']
|
2022-09-04 19:05:06 +02:00
|
|
|
|
= max
|
2022-09-19 20:33:27 +02:00
|
|
|
|
(
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$h
|
2022-09-19 20:33:27 +02:00
|
|
|
|
, $node['lh']
|
|
|
|
|
+ $mm['line_spacing']
|
2022-09-04 19:05:06 +02:00
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ calculate y and yo
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function calculate_y(&$mm)
|
|
|
|
|
{
|
|
|
|
|
$mm['map_top'] = 0;
|
|
|
|
|
$mm['map_bottom'] = 0;
|
|
|
|
|
$mm['map_height'] = $mm['nodes'][0]['h'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][0]['y'] = 0;
|
|
|
|
|
calculate_children_y($mm, 0);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function calculate_children_y(&$mm,$pid)
|
|
|
|
|
{
|
2022-09-09 21:35:23 +02:00
|
|
|
|
$y = $mm['nodes'][$pid]['y'];
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2022-09-09 21:35:23 +02:00
|
|
|
|
$mm['nodes'][$pid]['yo'] =
|
|
|
|
|
round(
|
|
|
|
|
(
|
|
|
|
|
+ $mm['nodes'][$pid]['h']
|
|
|
|
|
- $mm['nodes'][$pid]['lh']
|
|
|
|
|
)/2
|
|
|
|
|
)
|
|
|
|
|
;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2022-09-09 21:35:23 +02:00
|
|
|
|
if (!($mm['nodes'][$pid]['collapsed'] ?? false))
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($mm['nodes'][$pid]['visible_children'] as $cid)
|
2022-09-09 21:35:23 +02:00
|
|
|
|
{
|
|
|
|
|
$mm['nodes'][$cid]['y'] = $y;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2022-09-09 21:35:23 +02:00
|
|
|
|
$mm['map_bottom'] =
|
|
|
|
|
max
|
|
|
|
|
(
|
|
|
|
|
$mm['map_bottom']
|
|
|
|
|
,$mm['nodes'][$cid]['lh']
|
|
|
|
|
+$mm['line_spacing']
|
|
|
|
|
+$y
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$mm['map_top'] = min($mm['map_top'],$y);
|
|
|
|
|
$y += $mm['nodes'][$cid]['h'];
|
|
|
|
|
calculate_children_y($mm,$cid);
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ calculate top-down height shift
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function calculate_height_shift(&$mm, $id, $shift = 0)
|
|
|
|
|
{
|
|
|
|
|
$mm['nodes'][$id]['yo'] += $shift;
|
2023-01-07 22:46:24 +01:00
|
|
|
|
$shift += max(0, floor( (($mm['nodes'][$id]['lh'] - $mm['nodes'][$id]['clh']))/2 - 0.9 ));
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($mm['nodes'][$id]['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if (!$mm['nodes'][$id]['collapsed'])
|
|
|
|
|
calculate_height_shift($mm, $cid, $shift);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ draw connections on the map
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function draw_connections(&$mm, $id)
|
|
|
|
|
{
|
|
|
|
|
$node = $mm['nodes'][$id];
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$num_visible_children = count($mm['nodes'][$id]['visible_children']);
|
|
|
|
|
$num_children = count($mm['nodes'][$id]['children']);
|
|
|
|
|
$has_hidden_children = $num_visible_children != $num_children;
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
// if the node is collapsed
|
2023-03-19 08:55:57 +01:00
|
|
|
|
if ( ($node['collapsed'] ?? false) && ($num_children > 0) )
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-03-19 08:55:57 +01:00
|
|
|
|
if ($num_visible_children == $num_children)
|
2023-03-17 20:04:49 +01:00
|
|
|
|
mmput
|
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$node['x'] + $node['w']+1
|
|
|
|
|
,$node['y'] + $node['yo']
|
|
|
|
|
,' [+]'
|
|
|
|
|
);
|
|
|
|
|
else
|
|
|
|
|
mmput
|
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$node['x'] + $node['w']+1
|
|
|
|
|
,$node['y'] + $node['yo']
|
2023-03-19 15:20:27 +01:00
|
|
|
|
,'─╫─ [+]'
|
2023-03-17 20:04:49 +01:00
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// the easy part...
|
|
|
|
|
if ($num_visible_children==0)
|
|
|
|
|
{
|
|
|
|
|
if ($num_children>0)
|
|
|
|
|
mmput
|
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$node['x'] + $node['w'] + 1
|
|
|
|
|
,round( $node['y'] + $node['yo'] ) + round( ($node['lh'] ) / 2 - 0.6 )
|
|
|
|
|
,'─╫─'
|
|
|
|
|
);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
|
|
|
|
|
// if there's only one child: the same y coordinate
|
|
|
|
|
if ($num_visible_children==1)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$child_id = $node['visible_children'][ array_key_first( $node['visible_children'] ) ];
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$child = $mm['nodes'][ $child_id ];
|
|
|
|
|
|
|
|
|
|
$y1 = round( $node['y'] + $node['yo'] ) + round( ($node['lh'] ) / 2 - 0.6 );
|
|
|
|
|
$y2 = round( $child['y'] + $child['yo'] ) + round( ($child['lh']) / 2 - 0.6 );
|
|
|
|
|
|
2023-03-15 09:09:17 +01:00
|
|
|
|
$x =
|
|
|
|
|
$mm['align_levels']
|
|
|
|
|
? $node['x'] + $node['w'] - 2
|
|
|
|
|
: $child['x'] - conn_left_len - conn_right_len
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$line =
|
2023-03-17 20:04:49 +01:00
|
|
|
|
(
|
|
|
|
|
$has_hidden_children
|
|
|
|
|
? '─╫'
|
|
|
|
|
: '──'
|
|
|
|
|
)
|
|
|
|
|
.
|
|
|
|
|
(
|
|
|
|
|
$mm['align_levels']
|
2023-05-12 05:00:34 +02:00
|
|
|
|
? str_repeat('─', $child['x'] - $node['x'] - $node['w'] - 1)
|
2023-03-17 20:04:49 +01:00
|
|
|
|
: $mm['conn_single']
|
|
|
|
|
)
|
2023-03-15 09:09:17 +01:00
|
|
|
|
;
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
2023-03-15 09:09:17 +01:00
|
|
|
|
,$x
|
2022-09-04 19:05:06 +02:00
|
|
|
|
,min($y1,$y2)
|
2023-03-15 09:09:17 +01:00
|
|
|
|
,$line
|
2022-09-04 19:05:06 +02:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (abs(min($y1,$y2)-$y2)>0)
|
|
|
|
|
{
|
|
|
|
|
for ($yy=min($y1,$y2); $yy<max($y1,$y2); $yy++)
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$child['x'] - 2
|
|
|
|
|
,$yy
|
|
|
|
|
,'│'
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$child['x'] - 2
|
|
|
|
|
,$y2
|
|
|
|
|
,( $y2 > $y1 ? '╰' : '╭' )
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$child['x'] - 2
|
|
|
|
|
,min($y1,$y2)
|
|
|
|
|
,( $y2 > $y1 ? '╮' : '╯' )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
draw_connections($mm, $child_id );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if there's more than one child
|
|
|
|
|
$bottom = 0;
|
|
|
|
|
$bottom_child = 0;
|
|
|
|
|
$top = $mm['map_height'];
|
|
|
|
|
$top_child = 0;
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($node['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
if ($mm['nodes'][$cid]['y'] + $mm['nodes'][$cid]['yo'] > $bottom)
|
|
|
|
|
{
|
|
|
|
|
$bottom = $mm['nodes'][$cid]['y'] + $mm['nodes'][$cid]['yo'];
|
|
|
|
|
$bottom_child = $cid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($mm['nodes'][$cid]['y'] + $mm['nodes'][$cid]['yo'] < $top)
|
|
|
|
|
{
|
|
|
|
|
$top = $mm['nodes'][$cid]['y'] + $mm['nodes'][$cid]['yo'];
|
|
|
|
|
$top_child = $cid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$middle = round($node['y']+$node['yo']) + round($node['lh']/2-0.6);
|
|
|
|
|
|
2023-03-15 09:09:17 +01:00
|
|
|
|
$x =
|
|
|
|
|
$mm['align_levels']
|
|
|
|
|
? $node['x'] + $node['w'] - 2
|
|
|
|
|
: $mm['nodes'][$top_child]['x'] - conn_left_len - conn_right_len
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$line =
|
2023-03-17 20:04:49 +01:00
|
|
|
|
(
|
|
|
|
|
$has_hidden_children
|
|
|
|
|
? '─╫'
|
|
|
|
|
: '──'
|
|
|
|
|
)
|
|
|
|
|
.
|
|
|
|
|
(
|
|
|
|
|
$mm['align_levels']
|
2023-05-12 05:03:52 +02:00
|
|
|
|
? str_repeat('─', $mm['nodes'][$top_child]['x'] - $node['x'] - $node['w'] - 3 )
|
2023-03-17 20:04:49 +01:00
|
|
|
|
: $mm['conn_left']
|
|
|
|
|
)
|
2023-03-15 09:09:17 +01:00
|
|
|
|
;
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
2023-03-15 09:09:17 +01:00
|
|
|
|
,$x
|
2022-09-04 19:05:06 +02:00
|
|
|
|
,$middle
|
2023-03-15 09:09:17 +01:00
|
|
|
|
,$line
|
2022-09-04 19:05:06 +02:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for ( $i = $top ; $i < $bottom ; $i++ )
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$mm['nodes'][$top_child]['x'] - conn_right_len
|
|
|
|
|
,$i
|
|
|
|
|
,'│'
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$mm['nodes'][$top_child]['x'] - conn_right_len
|
|
|
|
|
,$top
|
|
|
|
|
,'╭'
|
|
|
|
|
.$mm['conn_right']
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$mm['nodes'][$top_child]['x']-conn_right_len
|
|
|
|
|
,$bottom
|
|
|
|
|
,'╰'
|
|
|
|
|
.$mm['conn_right']
|
|
|
|
|
);
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
if ($num_visible_children>2)
|
|
|
|
|
foreach ($node['visible_children'] as $cid)
|
|
|
|
|
if ($cid!=$top_child && $cid!=$bottom_child)
|
|
|
|
|
mmput
|
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$mm['nodes'][$cid]['x']-conn_right_len
|
|
|
|
|
,$mm['nodes'][$cid]['y']
|
|
|
|
|
+$mm['nodes'][$cid]['lh']/2-0.2
|
|
|
|
|
+$mm['nodes'][$cid]['yo']
|
|
|
|
|
,'├'
|
|
|
|
|
.$mm['conn_right']
|
|
|
|
|
);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$existing_char =
|
|
|
|
|
mb_substr
|
|
|
|
|
(
|
|
|
|
|
$mm['map'][$middle]
|
|
|
|
|
,$mm['nodes'][$top_child]['x'] - conn_right_len
|
|
|
|
|
,1
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ($existing_char=='│')
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$mm['nodes'][$top_child]['x'] - conn_right_len
|
|
|
|
|
,$middle
|
|
|
|
|
,'┤'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ($existing_char=='╭')
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$mm['nodes'][$top_child]['x'] - conn_right_len
|
|
|
|
|
,$middle
|
|
|
|
|
,'┬'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ($existing_char=='├')
|
2022-09-19 20:33:27 +02:00
|
|
|
|
mmput
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm
|
|
|
|
|
,$mm['nodes'][$top_child]['x'] - conn_right_len
|
|
|
|
|
,$middle
|
|
|
|
|
,'┼'
|
|
|
|
|
);
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($node['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
draw_connections($mm, $cid);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ add content to the map
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function add_content_to_the_map(&$mm, $id)
|
|
|
|
|
{
|
|
|
|
|
$node = $mm['nodes'][$id];
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$at_the_end =
|
|
|
|
|
$node['is_leaf']
|
|
|
|
|
|| ($node['collapsed'] ?? false)
|
|
|
|
|
|| count($node['visible_children']) == 0
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$max_width =
|
|
|
|
|
$at_the_end
|
|
|
|
|
? $mm['max_leaf_node_width']
|
|
|
|
|
: $mm['max_parent_node_width']
|
2022-09-04 19:05:06 +02:00
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
if ( mb_strlen($node['title']) > width_tolerance * $max_width)
|
|
|
|
|
$lines =
|
|
|
|
|
explode
|
|
|
|
|
(
|
2022-09-20 20:49:23 +02:00
|
|
|
|
PHP_EOL,
|
2022-09-04 19:05:06 +02:00
|
|
|
|
wordwrap
|
|
|
|
|
(
|
2022-09-20 20:49:23 +02:00
|
|
|
|
$node['title']
|
|
|
|
|
,$max_width
|
|
|
|
|
,PHP_EOL
|
2022-09-04 19:05:06 +02:00
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
else
|
|
|
|
|
$lines = [$node['title']];
|
|
|
|
|
|
|
|
|
|
$num_lines = count($lines);
|
|
|
|
|
for ( $i=0 ; $i<$num_lines ; $i++ )
|
2024-04-04 10:55:44 +02:00
|
|
|
|
mmputcontent
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
|
|
|
|
$mm,
|
|
|
|
|
$node['x'],
|
2022-09-15 19:50:55 +02:00
|
|
|
|
$node['y']+$node['yo']+$i,
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$lines[$i].' '
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!($node['collapsed'] ?? false))
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($node['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
add_content_to_the_map($mm,$cid);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ build map
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function build_map(&$mm)
|
|
|
|
|
{
|
|
|
|
|
// resetting the global values
|
|
|
|
|
$mm['map_width'] = 0;
|
|
|
|
|
$mm['map_height'] = 0;
|
|
|
|
|
$mm['map_top'] = 0;
|
|
|
|
|
$mm['map_bottom'] = 0;
|
|
|
|
|
|
|
|
|
|
// resetting the coordinates
|
|
|
|
|
foreach ($mm['nodes'] as $id=>$node)
|
|
|
|
|
{
|
|
|
|
|
$mm['nodes'][$id]['x'] = -1;
|
|
|
|
|
$mm['nodes'][$id]['y'] = -1;
|
|
|
|
|
$mm['nodes'][$id]['h'] = -1;
|
|
|
|
|
$mm['nodes'][$id]['lh'] = -1;
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$mm['nodes'][$id]['visible_children'] = $mm['nodes'][$id]['children'];
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][0]['x'] = 0;
|
|
|
|
|
$mm['nodes'][0]['w'] = left_padding;
|
|
|
|
|
$mm['nodes'][0]['lh'] = 1;
|
|
|
|
|
|
|
|
|
|
// resetting the map, 1/2
|
|
|
|
|
$mm['map']=[];
|
|
|
|
|
$mm['map_width']=0;
|
|
|
|
|
$mm['map_height']=0;
|
|
|
|
|
$mm['map_top']=0;
|
|
|
|
|
$mm['map_bottom']=0;
|
|
|
|
|
|
|
|
|
|
// calculating the new coordinates
|
2023-03-17 20:04:49 +01:00
|
|
|
|
if (!$mm['show_hidden'])
|
|
|
|
|
list_visible_children($mm, $mm['root_id']);
|
2022-09-19 20:33:27 +02:00
|
|
|
|
calculate_x_and_lh($mm,$mm['root_id']);
|
2023-03-15 09:09:17 +01:00
|
|
|
|
if ($mm['align_levels'])
|
|
|
|
|
calculate_aligned_x($mm,$mm['root_id'],$mm['nodes'][ $mm['root_id'] ]['w'] + conn_left_len + conn_right_len + 1);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
calculate_h($mm);
|
|
|
|
|
calculate_y($mm);
|
2022-09-19 20:33:27 +02:00
|
|
|
|
calculate_height_shift($mm, $mm['root_id']);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
// resetting the map, 2/2
|
|
|
|
|
$height = max($mm['map_bottom'],$mm['terminal_height']);
|
2024-04-04 10:55:44 +02:00
|
|
|
|
$blank = str_repeat(' ', max($mm['map_width'],$mm['terminal_width']));
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
for ($i=$mm['map_top'] ; $i<=$height ; $i++)
|
|
|
|
|
$mm['map'][$i] = $blank;
|
|
|
|
|
|
|
|
|
|
// building the new map
|
2022-09-19 20:33:27 +02:00
|
|
|
|
draw_connections($mm, $mm['root_id']);
|
|
|
|
|
add_content_to_the_map($mm, $mm['root_id']);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-10-13 12:30:38 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ toggle numbers
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function toggle_numbers()
|
2022-10-13 12:30:38 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
|
|
|
|
if ($mm['active_node'] <= $mm['root_id'])
|
2022-10-13 12:30:38 +02:00
|
|
|
|
return;
|
|
|
|
|
|
2023-01-07 12:29:42 +01:00
|
|
|
|
$padlen = count($mm['nodes'][ $mm['nodes'][$mm['active_node']]['parent'] ]['children']) > 9 ? 2 : 1;
|
|
|
|
|
|
2022-10-13 12:30:38 +02:00
|
|
|
|
$ordered= false;
|
|
|
|
|
$i=1;
|
|
|
|
|
foreach ($mm['nodes'][ $mm['nodes'][$mm['active_node']]['parent'] ]['children'] as $cid)
|
|
|
|
|
$ordered = $ordered || mb_ereg('^\d+\.',$mm['nodes'][$cid]['title']);
|
|
|
|
|
|
|
|
|
|
$i=1;
|
|
|
|
|
foreach ($mm['nodes'][ $mm['nodes'][$mm['active_node']]['parent'] ]['children'] as $cid)
|
|
|
|
|
if ($ordered)
|
|
|
|
|
$mm['nodes'][$cid]['title'] = mb_ereg_replace('^\d+\. *','',$mm['nodes'][$cid]['title']);
|
|
|
|
|
else
|
2023-01-07 12:29:42 +01:00
|
|
|
|
$mm['nodes'][$cid]['title'] = str_pad($i++, $padlen, '0', STR_PAD_LEFT).'. '.$mm['nodes'][$cid]['title'];
|
2022-10-13 12:30:38 +02:00
|
|
|
|
|
2023-07-23 11:22:48 +02:00
|
|
|
|
push_change($mm);
|
2022-10-13 12:30:38 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-10-12 13:25:21 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ toggle symbol
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function toggle_symbol()
|
2022-10-12 13:25:21 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2023-03-15 09:24:48 +01:00
|
|
|
|
$len1 = mb_strlen($mm['symbol1'])+1;
|
|
|
|
|
$len2 = mb_strlen($mm['symbol2'])+1;
|
|
|
|
|
|
|
|
|
|
$sym1 = mb_substr($mm['nodes'][ $mm['active_node'] ]['title'],0,$len1);
|
|
|
|
|
$sym2 = mb_substr($mm['nodes'][ $mm['active_node'] ]['title'],0,$len2);
|
|
|
|
|
|
|
|
|
|
if ($sym1==$mm['symbol1'].' ')
|
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] =
|
|
|
|
|
$mm['symbol2']
|
|
|
|
|
.' '
|
|
|
|
|
.mb_substr($mm['nodes'][ $mm['active_node'] ]['title'],$len1);
|
|
|
|
|
elseif ($sym2==$mm['symbol2'].' ')
|
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] =
|
|
|
|
|
mb_substr($mm['nodes'][ $mm['active_node'] ]['title'],$len2);
|
2022-10-12 13:25:21 +02:00
|
|
|
|
else
|
2023-03-15 09:24:48 +01:00
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] =
|
|
|
|
|
$mm['symbol1']
|
|
|
|
|
.' '
|
|
|
|
|
.$mm['nodes'][ $mm['active_node'] ]['title'];
|
2022-10-12 13:25:21 +02:00
|
|
|
|
|
2023-07-23 11:22:48 +02:00
|
|
|
|
push_change($mm);
|
2022-10-12 13:25:21 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ toggle hide
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function toggle_hide()
|
2023-03-17 20:04:49 +01:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
if ($mm['active_node'] == $mm['root_id'])
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
push_change($mm);
|
|
|
|
|
|
|
|
|
|
$is_hidden = false;
|
|
|
|
|
if ( substr($mm['nodes'][ $mm['active_node'] ]['title'], 0, 9) == '[HIDDEN] ')
|
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] = mb_substr( $mm['nodes'][ $mm['active_node'] ]['title'], 9 );
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] = '[HIDDEN] ' . $mm['nodes'][ $mm['active_node'] ]['title'];
|
|
|
|
|
$is_hidden = true;
|
2023-03-18 08:18:11 +01:00
|
|
|
|
move_active_node_to_sibling_or_parent($mm);
|
2023-03-17 20:04:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
message($mm, 'Hidden attribute is turned '.($is_hidden ? 'on' : 'off').' for the node.');
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function toggle_show_hidden()
|
2023-03-17 20:04:49 +01:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$mm['show_hidden'] = !$mm['show_hidden'];
|
2023-03-18 08:18:11 +01:00
|
|
|
|
move_active_node_to_sibling_or_parent($mm);
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
message($mm, 'Hidden nodes will '.($mm['show_hidden'] ? '' : 'not ').'be shown.');
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-18 08:18:11 +01:00
|
|
|
|
function move_active_node_to_sibling_or_parent(&$mm)
|
|
|
|
|
{
|
|
|
|
|
if ($mm['show_hidden'] || substr($mm['nodes'][ $mm['active_node'] ]['title'],0,9)!='[HIDDEN] ' )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
$parent_id = $mm['nodes'][ $mm['active_node'] ]['parent'];
|
|
|
|
|
if (count($mm['nodes'][$parent_id]['visible_children'])<=1)
|
|
|
|
|
$mm['active_node'] = $parent_id;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$passed = false;
|
|
|
|
|
|
|
|
|
|
// getting the next sibling
|
|
|
|
|
foreach ($mm['nodes'][$parent_id]['children'] as $cid)
|
|
|
|
|
if ($cid==$mm['active_node'])
|
|
|
|
|
$passed = true;
|
|
|
|
|
elseif ($passed && substr($mm['nodes'][$cid]['title'],0,9)!='[HIDDEN] ')
|
|
|
|
|
{
|
|
|
|
|
$mm['active_node'] = $cid;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// so, there's no item after it!
|
2023-03-18 08:34:00 +01:00
|
|
|
|
$mm['active_node'] = $parent_id;
|
2023-03-18 08:18:11 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
|
2023-03-15 09:09:17 +01:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ toggle align
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function toggle_align()
|
2023-03-15 09:09:17 +01:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
2023-03-15 09:09:17 +01:00
|
|
|
|
$mm['align_levels'] = !$mm['align_levels'];
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// {{{ toggle node
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function toggle_node()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-10 09:57:00 +02:00
|
|
|
|
if ($mm['nodes'][ $mm['active_node'] ]['is_leaf'])
|
|
|
|
|
$mm['active_node'] = $mm['nodes'][ $mm['active_node'] ]['parent'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['collapsed'] =
|
|
|
|
|
!($mm['nodes'][ $mm['active_node'] ]['collapsed'] ?? false);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// {{{ change line spacing
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function increase_line_spacing()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
change_line_spacing($mm, +1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function decrease_line_spacing()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
change_line_spacing($mm, -1);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function change_line_spacing(&$mm, $amount)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['line_spacing'] = max(0, $mm['line_spacing'] + $amount);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2022-09-04 19:05:06 +02:00
|
|
|
|
display($mm);
|
|
|
|
|
message($mm,'Spacing: '.$mm['line_spacing']);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// {{{ change max node width
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function increase_text_width()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
change_max_node_width($mm, width_change_factor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function decrease_text_width()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
change_max_node_width($mm, 1/width_change_factor);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function change_max_node_width(&$mm, $amount)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mx = $mm['terminal_width'] - max_width_padding;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['max_parent_node_width'] = round(min($mx, max( width_min, $mm['max_parent_node_width'] * $amount )));
|
|
|
|
|
$mm['max_leaf_node_width'] = round(min($mx, max( width_min, $mm['max_leaf_node_width'] * $amount )));
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
build_map($mm);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2022-09-04 19:05:06 +02:00
|
|
|
|
display($mm);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
message($mm,'Width: '.$mm['max_parent_node_width'].' / '.$mm['max_leaf_node_width']);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
// {{{ push node down
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function push_node_down(&$mm, $id)
|
|
|
|
|
{
|
2023-03-17 20:04:49 +01:00
|
|
|
|
if ($id==$mm['root_id'])
|
|
|
|
|
return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 02:50:35 +02:00
|
|
|
|
push_change($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if (isset($mm['nodes'][$id+1]))
|
|
|
|
|
push_node_down($mm,$id+1);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][$id+1] = $mm['nodes'][$id];
|
|
|
|
|
unset($mm['nodes'][$id]);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][ $mm['nodes'][$id+1]['parent'] ]['children'] =
|
|
|
|
|
array_diff
|
|
|
|
|
(
|
|
|
|
|
$mm['nodes'][ $mm['nodes'][$id+1]['parent'] ]['children'],
|
|
|
|
|
[$id]
|
|
|
|
|
);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][ $mm['nodes'][$id+1]['parent'] ]['children'] =
|
|
|
|
|
array_push
|
|
|
|
|
(
|
|
|
|
|
$mm['nodes'][ $mm['nodes'][$id+1]['parent'] ]['children'],
|
|
|
|
|
[$id+1]
|
|
|
|
|
);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach($mm['nodes'][$id+1]['children'] as $cid=>$cdata)
|
|
|
|
|
$mm['nodes'][$cid]['parent'] = $id+1;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ insert node
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
|
|
|
|
|
function insert_new_child()
|
|
|
|
|
{
|
|
|
|
|
insert_new_node(insert_child);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function insert_new_sibling()
|
|
|
|
|
{
|
|
|
|
|
insert_new_node(insert_sibling);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function insert_new_node($type)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($mm['active_node']==$mm['root_id'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$type=insert_child;
|
|
|
|
|
|
|
|
|
|
if ($type==insert_sibling)
|
|
|
|
|
$parent_id = $mm['nodes'][ $mm['active_node'] ]['parent'];
|
|
|
|
|
else
|
|
|
|
|
$parent_id = $mm['active_node'];
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][$parent_id]['is_leaf'] = false;
|
|
|
|
|
$mm['nodes'][$parent_id]['collapsed'] = false;
|
|
|
|
|
|
|
|
|
|
$new_id = max(array_keys($mm['nodes'])) + 1;
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][$new_id] =
|
|
|
|
|
[
|
|
|
|
|
'title' => 'NEW',
|
|
|
|
|
'is_leaf' => true,
|
|
|
|
|
'collapsed' => false,
|
|
|
|
|
'children' => [],
|
|
|
|
|
'parent' => $parent_id
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if ($type==insert_sibling)
|
|
|
|
|
{
|
|
|
|
|
$children = [];
|
|
|
|
|
foreach ($mm['nodes'][$parent_id]['children'] as $child)
|
|
|
|
|
{
|
|
|
|
|
$children[] = $child;
|
|
|
|
|
if ($child==$mm['active_node'])
|
|
|
|
|
$children[] = $new_id;
|
|
|
|
|
}
|
|
|
|
|
$mm['nodes'][$parent_id]['children'] = $children;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
$mm['nodes'][$parent_id]['children'][] = $new_id;
|
|
|
|
|
|
|
|
|
|
$mm['active_node'] = $new_id;
|
|
|
|
|
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
|
2022-10-24 10:49:26 +02:00
|
|
|
|
push_change($mm);
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title']='';
|
|
|
|
|
edit_node($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
2022-09-16 20:00:40 +02:00
|
|
|
|
// {{{ magic readline!
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 20:00:40 +02:00
|
|
|
|
function magic_readline(&$mm, $title)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
$in = '';
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$cursor = mb_strlen($title)+1;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$shift = max( 0, $cursor - $mm['terminal_width'] );
|
|
|
|
|
|
|
|
|
|
show_line($mm, $title, $cursor, $shift);
|
|
|
|
|
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
2022-09-16 14:31:09 +02:00
|
|
|
|
usleep(5000);
|
2022-09-16 20:21:40 +02:00
|
|
|
|
$in = fread(STDIN, 66666);
|
|
|
|
|
// normally, the longest sequence we have is 13 bytes,
|
|
|
|
|
// but if ctrl+shift+v is used, the whole text will be passed!
|
|
|
|
|
// In other words, we don't receive a ctrl+shift+v input,
|
|
|
|
|
// but the actual content. Was that a confusing behavior? Of course!!!
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
if ($in != '')
|
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
if ($in==special_keys['esc'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
display($mm);
|
2022-09-16 20:00:40 +02:00
|
|
|
|
return false;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['arr_up'] || $in==special_keys['home'])
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$cursor = 1;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['arr_right'])
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$cursor = min( mb_strlen($title)+1, $cursor+1);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['arr_down'] || $in==special_keys['end'])
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$cursor = mb_strlen($title)+1;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['arr_left'])
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$cursor = max(1, $cursor-1);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['ctrl_arr_left'] || $in==special_keys['shift_arr_left'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$cursor =
|
|
|
|
|
$cursor < 3
|
|
|
|
|
? 1
|
|
|
|
|
: max
|
|
|
|
|
(
|
|
|
|
|
1,
|
|
|
|
|
(
|
2022-09-15 18:37:21 +02:00
|
|
|
|
mb_strrpos($title,' ',$cursor-mb_strlen($title)-3) !== false
|
|
|
|
|
? mb_strrpos($title,' ',$cursor-mb_strlen($title)-3) + 2
|
2022-09-04 19:05:06 +02:00
|
|
|
|
: 1
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['ctrl_arr_right'] || $in==special_keys['shift_arr_right'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$cursor =
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$cursor > mb_strlen($title) -2
|
|
|
|
|
? mb_strlen($title) + 1
|
2022-09-04 19:05:06 +02:00
|
|
|
|
: min
|
|
|
|
|
(
|
2022-09-15 18:37:21 +02:00
|
|
|
|
mb_strlen($title)+1,
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
2022-09-15 18:37:21 +02:00
|
|
|
|
mb_strpos($title,' ',$cursor+1) !== false
|
|
|
|
|
? mb_strpos($title,' ',$cursor+1) + 2
|
|
|
|
|
: mb_strlen($title) + 1
|
2022-09-04 19:05:06 +02:00
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// ctrl+backspace
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['ctrl_back_space'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2024-04-08 08:26:55 +02:00
|
|
|
|
$from =
|
2022-09-25 08:58:19 +02:00
|
|
|
|
max
|
|
|
|
|
(
|
|
|
|
|
0
|
|
|
|
|
,mb_strrpos
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,' '
|
|
|
|
|
,max
|
|
|
|
|
(
|
|
|
|
|
-mb_strlen($title)
|
|
|
|
|
,$cursor-mb_strlen($title)-3
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
;
|
2024-04-08 08:26:55 +02:00
|
|
|
|
$title =
|
2022-09-25 08:58:19 +02:00
|
|
|
|
mb_substr($title, 0, $from + ($from>0) )
|
2022-09-25 09:14:33 +02:00
|
|
|
|
.mb_substr($title, $cursor-1)
|
|
|
|
|
;
|
2022-09-25 08:58:19 +02:00
|
|
|
|
$cursor = $from+1+($from>0);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['back_space'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
if ($cursor>1)
|
|
|
|
|
{
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$title =
|
|
|
|
|
mb_substr
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,0
|
|
|
|
|
,$cursor-2
|
|
|
|
|
)
|
|
|
|
|
.mb_substr
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,$cursor-1
|
|
|
|
|
);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$cursor--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['ctrl_del'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-25 09:14:33 +02:00
|
|
|
|
$len = mb_strlen($title);
|
2024-04-08 08:26:55 +02:00
|
|
|
|
$from =
|
2022-09-25 09:14:33 +02:00
|
|
|
|
mb_strpos
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,' '
|
|
|
|
|
,min
|
|
|
|
|
(
|
|
|
|
|
$cursor+1
|
|
|
|
|
,$len
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
if ($from===false)
|
|
|
|
|
$from=$len;
|
2024-04-08 08:26:55 +02:00
|
|
|
|
$title =
|
2022-09-25 09:14:33 +02:00
|
|
|
|
mb_substr($title, 0, $cursor-1)
|
|
|
|
|
.mb_substr($title, $from+1 )
|
|
|
|
|
;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['del'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$title =
|
|
|
|
|
mb_substr
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,0
|
|
|
|
|
,$cursor-1
|
|
|
|
|
)
|
|
|
|
|
.mb_substr
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,$cursor
|
|
|
|
|
);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['enter'])
|
2022-09-16 20:00:40 +02:00
|
|
|
|
return trim($title);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
elseif ($in==special_keys['ctrl_v'])
|
2022-09-15 17:29:44 +02:00
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$content =
|
2022-09-15 17:29:44 +02:00
|
|
|
|
trim
|
|
|
|
|
(
|
2022-09-16 14:37:56 +02:00
|
|
|
|
str_replace
|
2022-09-15 17:29:44 +02:00
|
|
|
|
(
|
2022-09-16 14:37:56 +02:00
|
|
|
|
["\n", "\r", "\t"]
|
|
|
|
|
,[" ", "", " " ]
|
|
|
|
|
,get_from_clipboard($mm)
|
2022-09-15 17:29:44 +02:00
|
|
|
|
)
|
|
|
|
|
);
|
2022-09-15 18:37:21 +02:00
|
|
|
|
|
|
|
|
|
$title =
|
|
|
|
|
mb_substr
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,0
|
|
|
|
|
,$cursor-1
|
|
|
|
|
)
|
|
|
|
|
.$content
|
|
|
|
|
.mb_substr
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,$cursor-1
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-15 17:29:44 +02:00
|
|
|
|
$cursor += mb_strlen($content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
// normal characters
|
2022-09-15 18:37:21 +02:00
|
|
|
|
else
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
if ($in==special_keys['tab'])
|
|
|
|
|
$in=' ';
|
2022-09-15 19:50:55 +02:00
|
|
|
|
|
2022-09-15 18:37:21 +02:00
|
|
|
|
$title =
|
|
|
|
|
mb_substr
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,0
|
|
|
|
|
,$cursor-1
|
|
|
|
|
)
|
|
|
|
|
.$in
|
|
|
|
|
.mb_substr
|
|
|
|
|
(
|
|
|
|
|
$title
|
|
|
|
|
,$cursor-1
|
2022-09-16 14:31:09 +02:00
|
|
|
|
)
|
|
|
|
|
;
|
2022-09-15 19:50:55 +02:00
|
|
|
|
|
2022-10-29 12:18:55 +02:00
|
|
|
|
$title = str_replace(["\n","\r","\t"],[" ",""," "],$title);
|
2022-09-17 00:41:45 +02:00
|
|
|
|
$title = mb_ereg_replace("[\000-\010\013-\037\177]|".BOM,'',$title);
|
2022-09-16 20:21:40 +02:00
|
|
|
|
$cursor += mb_strlen($in);
|
|
|
|
|
// the input content can be longer than one character if
|
|
|
|
|
// the user uses ctrl+shift+v to paste.
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// adjusting the position and shift
|
|
|
|
|
|
|
|
|
|
$shift = max( 0, $shift, $cursor - $mm['terminal_width'] );
|
|
|
|
|
$shift = min( $shift, $cursor-1 );
|
|
|
|
|
|
|
|
|
|
show_line($mm, $title, $cursor, $shift);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-16 20:00:40 +02:00
|
|
|
|
function show_line(&$mm, $title, $cursor, $shift)
|
|
|
|
|
{
|
|
|
|
|
$output = mb_substr($title,$shift,$mm['terminal_width']-1);
|
2024-04-04 10:55:44 +02:00
|
|
|
|
$output .= str_repeat( ' ' ,$mm['terminal_width'] - mb_strwidth($output) );
|
2022-09-16 20:00:40 +02:00
|
|
|
|
|
|
|
|
|
// showing the cursor
|
|
|
|
|
$output =
|
|
|
|
|
mb_substr
|
|
|
|
|
(
|
|
|
|
|
$output
|
|
|
|
|
,0
|
|
|
|
|
,$cursor-$shift-1
|
|
|
|
|
)
|
|
|
|
|
.invert_on
|
|
|
|
|
.mb_substr
|
|
|
|
|
(
|
|
|
|
|
$output
|
|
|
|
|
,$cursor-$shift-1
|
|
|
|
|
,1
|
|
|
|
|
)
|
|
|
|
|
.invert_off
|
|
|
|
|
.mb_substr
|
|
|
|
|
(
|
|
|
|
|
$output
|
|
|
|
|
,$cursor-$shift
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
echo
|
|
|
|
|
"\033["
|
|
|
|
|
.$mm['terminal_height'] //y
|
|
|
|
|
.";0f" // 0 -> x
|
|
|
|
|
.$mm['active_node_color']
|
|
|
|
|
.$output
|
|
|
|
|
;
|
2022-09-16 20:00:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ edit node
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function edit_node_append()
|
|
|
|
|
{
|
|
|
|
|
edit_node(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function edit_node_replace()
|
2022-09-16 20:00:40 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
edit_node(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function edit_node($rewrite = false)
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
2022-09-16 20:00:40 +02:00
|
|
|
|
$title = $rewrite ? '' : $mm['nodes'][ $mm['active_node'] ]['title'];
|
2022-09-24 10:54:08 +02:00
|
|
|
|
|
2022-10-24 10:49:26 +02:00
|
|
|
|
if
|
2022-09-24 10:54:08 +02:00
|
|
|
|
(
|
|
|
|
|
(
|
2022-09-25 08:58:19 +02:00
|
|
|
|
$mm['active_node']==$mm['root_id']
|
2022-09-24 10:54:08 +02:00
|
|
|
|
&& $title=='root'
|
|
|
|
|
)
|
|
|
|
|
or $title=='NEW'
|
|
|
|
|
)
|
2022-10-24 10:49:26 +02:00
|
|
|
|
$title = '';
|
2022-09-16 20:00:40 +02:00
|
|
|
|
|
|
|
|
|
$output = magic_readline($mm, $title);
|
|
|
|
|
|
2022-10-24 10:49:26 +02:00
|
|
|
|
if
|
|
|
|
|
(
|
|
|
|
|
(
|
|
|
|
|
$output === false
|
|
|
|
|
or $output === ''
|
|
|
|
|
)
|
2022-10-29 11:07:11 +02:00
|
|
|
|
&& $mm['nodes'][ $mm['active_node'] ]['title'] === ''
|
2022-10-24 10:49:26 +02:00
|
|
|
|
&& $mm['nodes'][ $mm['active_node'] ]['is_leaf']
|
|
|
|
|
)
|
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
delete_node_vh($mm, false, true);
|
2022-10-24 10:49:26 +02:00
|
|
|
|
push_change($mm);
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-16 20:00:40 +02:00
|
|
|
|
if ($output === false)
|
|
|
|
|
{
|
|
|
|
|
display($mm);
|
|
|
|
|
message($mm, 'Editing cancelled');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] = $output;
|
|
|
|
|
|
|
|
|
|
push_change($mm);
|
|
|
|
|
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ center active node
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function center_active_node()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
center_active_node_vh(false);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toggle_center_lock()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
$mm['center_lock'] = !$mm['center_lock'];
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function center_active_node_vh($only_vertically = false)
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$node = $mm['nodes'][ $mm['active_node'] ];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$midx = $node['w']/2 + $node['x'];
|
|
|
|
|
$midy = $node['lh']/2 + $node['y'] + $node['yo'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if (!$only_vertically)
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['viewport_left'] = max(0, round( $midx - $mm['terminal_width']/2 ) );
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['viewport_top'] = round( $midy - $mm['terminal_height']/2 );
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ goto's
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function go_to_root()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['active_node']=$mm['root_id'];
|
2022-09-04 19:05:06 +02:00
|
|
|
|
display($mm, true);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function go_up()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
change_active_node($mm,0,-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function go_down()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
change_active_node($mm,0,1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function go_left()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
change_active_node($mm,-1,0);
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function go_to_top()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$yid = 0;
|
|
|
|
|
$y = $mm['map_height'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($mm['nodes'] as $id=>$node)
|
|
|
|
|
if ($node['y']>=0 && $node['y']+$node['yo'] < $y)
|
|
|
|
|
{
|
|
|
|
|
$y = $node['y']+$node['yo'];
|
|
|
|
|
$yid = $id;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['active_node'] = $yid;
|
|
|
|
|
display($mm, true);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function go_right()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
change_active_node($mm,1,0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function go_to_bottom()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$yid = 0;
|
|
|
|
|
$y = 0;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($mm['nodes'] as $id=>$node)
|
|
|
|
|
if ($node['y']>=0 && $node['y']+$node['yo'] > $y)
|
|
|
|
|
{
|
|
|
|
|
$y = $node['y']+$node['yo']+$node['lh'];
|
|
|
|
|
$yid = $id;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['active_node'] = $yid;
|
|
|
|
|
display($mm, true);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-23 11:09:17 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ help
|
|
|
|
|
|
|
|
|
|
function help()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
global $mm;
|
|
|
|
|
global $keybindings;
|
|
|
|
|
|
|
|
|
|
$keynames = array_flip(special_keys);
|
|
|
|
|
|
|
|
|
|
$commands = [];
|
|
|
|
|
foreach ($keybindings as $key => $command)
|
|
|
|
|
$commands[$command][] = ( $keynames[$key] ?? $key );
|
|
|
|
|
|
|
|
|
|
$output = [];
|
|
|
|
|
foreach ($commands as $command => $keys)
|
|
|
|
|
$output[] =
|
|
|
|
|
str_pad($command.' ',32,'.',STR_PAD_RIGHT)
|
|
|
|
|
.' '
|
|
|
|
|
.implode(', ',$keys);
|
|
|
|
|
|
|
|
|
|
sort($output);
|
|
|
|
|
|
|
|
|
|
$breakpoint = floor((count($output)-1)/2);
|
|
|
|
|
|
|
|
|
|
for ($i=0 ; $i<=$breakpoint ; $i++)
|
|
|
|
|
echo
|
|
|
|
|
' '
|
|
|
|
|
.str_pad($output[$i],56,' ',STR_PAD_RIGHT)
|
|
|
|
|
.
|
|
|
|
|
($output[$i+$breakpoint+1] ?? '')
|
|
|
|
|
."\n"
|
|
|
|
|
;
|
|
|
|
|
echo "\n";
|
|
|
|
|
|
|
|
|
|
message($mm, "Press any key to exit this help screen.");
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
usleep(20000);
|
|
|
|
|
$in = fread(STDIN, 16);
|
|
|
|
|
if ($in != '')
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
display($mm);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ search
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function search()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-16 20:00:40 +02:00
|
|
|
|
$mm['query'] = magic_readline($mm,'');
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if (empty($mm['query']))
|
|
|
|
|
{
|
|
|
|
|
display($mm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
if (!next_search_result())
|
|
|
|
|
previous_search_result();
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function previous_search_result()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$cy
|
|
|
|
|
= $mm['nodes'][ $mm['active_node'] ]['y']
|
|
|
|
|
+ $mm['nodes'][ $mm['active_node'] ]['yo']
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$ny = -1;
|
|
|
|
|
$nid = -1;
|
|
|
|
|
|
|
|
|
|
foreach ($mm['nodes'] as $id=>$node)
|
|
|
|
|
if
|
|
|
|
|
(
|
|
|
|
|
$id != 0 &&
|
2023-03-17 20:04:49 +01:00
|
|
|
|
(
|
|
|
|
|
$mm['show_hidden'] ||
|
|
|
|
|
substr($node['title'],0,9) != '[HIDDEN] '
|
|
|
|
|
) &&
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$node['y'] > -1 &&
|
|
|
|
|
$node['y']+$node['yo'] < $cy &&
|
|
|
|
|
$node['y']+$node['yo'] > $ny &&
|
|
|
|
|
mb_stripos($node['title'],$mm['query'])!==false
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
$ny = $node['y'] + $node['yo'];
|
|
|
|
|
$nid = $id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($nid<0)
|
2022-09-16 14:47:47 +02:00
|
|
|
|
{
|
|
|
|
|
display($mm);
|
2022-09-10 00:30:05 +02:00
|
|
|
|
return false;
|
2022-09-16 14:47:47 +02:00
|
|
|
|
}
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
$mm['active_node'] = $nid;
|
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function next_search_result()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$cy
|
|
|
|
|
= $mm['nodes'][ $mm['active_node'] ]['y']
|
|
|
|
|
+ $mm['nodes'][ $mm['active_node'] ]['yo']
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$ny = $mm['map_height']+1;
|
|
|
|
|
$nid = -1;
|
|
|
|
|
|
|
|
|
|
foreach ($mm['nodes'] as $id=>$node)
|
|
|
|
|
if
|
|
|
|
|
(
|
|
|
|
|
$id != 0 &&
|
2023-03-17 20:04:49 +01:00
|
|
|
|
(
|
|
|
|
|
$mm['show_hidden'] ||
|
|
|
|
|
substr($node['title'],0,9) != '[HIDDEN] '
|
|
|
|
|
) &&
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$node['y'] > -1 &&
|
|
|
|
|
$node['y']+$node['yo'] > $cy &&
|
|
|
|
|
$node['y']+$node['yo'] < $ny &&
|
|
|
|
|
mb_stripos($node['title'],$mm['query'])!==false
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
$ny = $node['y'] + $node['yo'];
|
|
|
|
|
$nid = $id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($nid<0)
|
2022-09-10 00:30:05 +02:00
|
|
|
|
return false;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
$mm['active_node'] = $nid;
|
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ move active node
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function move_node_down()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($mm['active_node']==0) return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 02:50:35 +02:00
|
|
|
|
push_change($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$parent_id = $mm['nodes'][ $mm['active_node'] ]['parent'];
|
|
|
|
|
$children = [];
|
2023-03-18 08:18:11 +01:00
|
|
|
|
$just_passed_active = false;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($mm['nodes'][ $parent_id ]['children'] as $child)
|
|
|
|
|
{
|
|
|
|
|
if ($child!=$mm['active_node'])
|
|
|
|
|
$children[] = $child;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-18 08:18:11 +01:00
|
|
|
|
if ($just_passed_active && ($mm['show_hidden'] || substr($mm['nodes'][$child]['title'],0,9)!='[HIDDEN] ' ) )
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
$children[] = $mm['active_node'];
|
2023-03-18 08:18:11 +01:00
|
|
|
|
$just_passed_active = false;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($child==$mm['active_node'])
|
2023-03-18 08:18:11 +01:00
|
|
|
|
$just_passed_active = true;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-18 08:18:11 +01:00
|
|
|
|
if ($just_passed_active)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$children[] = $mm['active_node'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][ $parent_id ]['children'] = $children;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function move_node_up()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($mm['active_node']==0) return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 02:50:35 +02:00
|
|
|
|
push_change($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$parent_id = $mm['nodes'][ $mm['active_node'] ]['parent'];
|
|
|
|
|
$children = [];
|
2023-03-18 08:18:11 +01:00
|
|
|
|
$just_passed_active = false;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$rev_children = array_reverse($mm['nodes'][$parent_id]['children']);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($rev_children as $child)
|
|
|
|
|
{
|
|
|
|
|
if ($child!=$mm['active_node'])
|
|
|
|
|
$children[] = $child;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-18 08:18:11 +01:00
|
|
|
|
if ($just_passed_active && ($mm['show_hidden'] || substr($mm['nodes'][$child]['title'],0,9)!='[HIDDEN] ' ) )
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
$children[] = $mm['active_node'];
|
2023-03-18 08:18:11 +01:00
|
|
|
|
$just_passed_active = false;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($child==$mm['active_node'])
|
2023-03-18 08:18:11 +01:00
|
|
|
|
$just_passed_active = true;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-18 08:18:11 +01:00
|
|
|
|
if ($just_passed_active)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$children[] = $mm['active_node'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][ $parent_id ]['children'] = array_reverse($children);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-07 15:11:13 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ export html
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function export_html()
|
2022-09-07 15:11:13 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-07 15:11:13 +02:00
|
|
|
|
if (empty($mm['filename']))
|
|
|
|
|
{
|
|
|
|
|
message($mm, "Can't export the map when it doesn't have a file name yet. Save it first.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$file = fopen($mm['filename'].'.html', "w");
|
|
|
|
|
|
|
|
|
|
if ($file===false)
|
|
|
|
|
{
|
|
|
|
|
message($mm, 'ERROR! Could not save the file');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fwrite
|
|
|
|
|
(
|
|
|
|
|
$file
|
|
|
|
|
,'<!DOCTYPE html>'
|
2022-09-09 21:35:23 +02:00
|
|
|
|
.'<html lang=en>'
|
2022-09-07 15:11:13 +02:00
|
|
|
|
.'<head>'
|
2022-09-09 21:35:23 +02:00
|
|
|
|
.'<title>'
|
2022-09-19 20:33:27 +02:00
|
|
|
|
.$mm['nodes'][ $mm['root_id'] ]['title']
|
2022-09-09 21:35:23 +02:00
|
|
|
|
.'</title>'
|
|
|
|
|
.'<meta charset="UTF-8">'
|
2022-09-18 13:39:49 +02:00
|
|
|
|
.'<meta name=viewport content="width=device-width,initial-scale=1,user-scalable=yes">'
|
2022-09-07 15:11:13 +02:00
|
|
|
|
.'<style>'
|
2022-09-07 15:15:02 +02:00
|
|
|
|
.'body { background-color: #222; color: #ddd; font-family: monospace; padding: 0; font-size: 16px; }'
|
2022-09-07 15:11:13 +02:00
|
|
|
|
.'#root {margin:10px 0}'
|
|
|
|
|
.'p:before { content: "━ "; }'
|
2022-09-09 21:35:23 +02:00
|
|
|
|
.'p, summary { padding: 8px; margin: 0; font-size: 16px; }'
|
|
|
|
|
.'details, p { padding-left: 29px; border-left: 3px solid #444; font-size:16px; }'
|
2022-09-07 15:11:13 +02:00
|
|
|
|
.'summary { margin-left: -10px; cursor: pointer; }'
|
2022-09-07 15:15:02 +02:00
|
|
|
|
.'summary:hover, p:hover { color: #fbc531; }'
|
2022-09-07 15:11:13 +02:00
|
|
|
|
.'details:hover, p:hover { border-color: #e1b12c; }'
|
|
|
|
|
.'#source { position: absolute; bottom: 0; left: 0; padding: 5px 15px 8px 15px; margin: 100px 0 0 0; }'
|
|
|
|
|
.'#source { background-color: #333; border: none; box-sizing: border-box;}'
|
|
|
|
|
.'#source > summary { list-style: none; }'
|
2022-09-09 21:35:23 +02:00
|
|
|
|
.'#source[open] { position: static; margin: 100px 0 0 0; font-size: 16px; }'
|
2022-09-07 15:11:13 +02:00
|
|
|
|
.'#map { margin: 40px 30px; }'
|
|
|
|
|
.'</style>'
|
|
|
|
|
.'</head>'
|
|
|
|
|
.'<body>'
|
|
|
|
|
.'<div id=map>'
|
2022-09-19 20:33:27 +02:00
|
|
|
|
.export_html_node($mm, $mm['root_id'])
|
2022-09-07 15:11:13 +02:00
|
|
|
|
.'</div>'
|
|
|
|
|
.'<details id=source>'
|
|
|
|
|
.'<summary>This is a limited, read-only version of a mind-map created in h-m-m | view source!</summary>'
|
|
|
|
|
.'<pre>'
|
2022-09-19 20:33:27 +02:00
|
|
|
|
.map_to_list($mm,$mm['root_id'])
|
2022-09-07 15:11:13 +02:00
|
|
|
|
.'</pre>'
|
|
|
|
|
.'</details>'
|
|
|
|
|
.'</body>'
|
|
|
|
|
.'</html>'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
fclose($file);
|
|
|
|
|
|
|
|
|
|
message($mm, 'Exported as '.$mm['filename'].'.html');
|
2022-09-15 09:51:32 +02:00
|
|
|
|
copy_to_clipboard($mm, $mm['filename'].'.html');
|
2022-09-29 10:14:11 +02:00
|
|
|
|
$filename = getenv('PWD').'/'.basename($mm['filename']).'.html';
|
|
|
|
|
|
|
|
|
|
if ($mm['post_export_command']!='')
|
|
|
|
|
{
|
|
|
|
|
message($mm, 'Running the "'.$mm['post_export_command'].'" command');
|
|
|
|
|
exec(str_replace('%filename%', $filename, $mm['post_export_command']), $output, $result);
|
|
|
|
|
display($mm);
|
|
|
|
|
message($mm, 'Post-export command ended ('.$result.')');
|
|
|
|
|
}
|
2022-09-07 15:11:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function export_html_node(&$mm, $parent_id)
|
|
|
|
|
{
|
2023-03-17 20:04:49 +01:00
|
|
|
|
if ($mm['nodes'][$parent_id]['visible_children']==[])
|
2022-09-07 15:11:13 +02:00
|
|
|
|
{
|
|
|
|
|
$output =
|
|
|
|
|
"<p>"
|
|
|
|
|
.$mm['nodes'][$parent_id]['title']
|
|
|
|
|
."</p>";
|
|
|
|
|
}
|
2022-09-19 20:33:27 +02:00
|
|
|
|
elseif ($parent_id==$mm['root_id'])
|
2022-09-07 15:11:13 +02:00
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$output =
|
2022-09-07 15:11:13 +02:00
|
|
|
|
"<div id=root>"
|
|
|
|
|
.$mm['nodes'][$parent_id]['title']
|
|
|
|
|
."</div>";
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($mm['nodes'][$parent_id]['visible_children'] as $cid)
|
2022-09-07 15:11:13 +02:00
|
|
|
|
$output .= export_html_node($mm, $cid);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$output =
|
|
|
|
|
"<details>"
|
|
|
|
|
."<summary>"
|
2022-09-17 11:42:21 +02:00
|
|
|
|
.$mm['nodes'][$parent_id]['title']
|
2022-09-07 15:11:13 +02:00
|
|
|
|
."</summary>";
|
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($mm['nodes'][$parent_id]['visible_children'] as $cid)
|
2022-09-07 15:11:13 +02:00
|
|
|
|
$output .= export_html_node($mm, $cid);
|
|
|
|
|
|
|
|
|
|
$output .=
|
|
|
|
|
"</details>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-02-05 08:23:29 +01:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ export text
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function export_text()
|
2023-02-05 08:23:29 +01:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2023-03-18 14:38:26 +01:00
|
|
|
|
$output = '';
|
|
|
|
|
foreach ($mm['map'] as $line)
|
|
|
|
|
if (rtrim($line) != '')
|
|
|
|
|
$output .= substr(rtrim($line),3)."\n";
|
2023-02-05 08:23:29 +01:00
|
|
|
|
|
2023-03-18 14:38:26 +01:00
|
|
|
|
copy_to_clipboard($mm, $output);
|
|
|
|
|
message($mm, 'Exported the map to clipboard.');
|
2023-02-05 08:23:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ save
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function save()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
2023-07-23 11:22:48 +02:00
|
|
|
|
if ($mm['auto_save'])
|
|
|
|
|
message($mm,'auto_save is enabled and you don\'t need to save manually.');
|
|
|
|
|
else
|
|
|
|
|
save_vh($mm, false);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function save_as()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
save_vh($mm, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function save_vh(&$mm, $new_name = false)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-16 20:00:40 +02:00
|
|
|
|
if ($new_name || empty($mm['filename']))
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-20 11:38:06 +02:00
|
|
|
|
$path = getenv('PWD');
|
|
|
|
|
|
|
|
|
|
if (substr($path,-1,1) != '/')
|
|
|
|
|
$path .= '/';
|
|
|
|
|
|
|
|
|
|
if (empty($mm['filename']) && $mm['nodes'][ $mm['root_id'] ]['title'] != 'root')
|
|
|
|
|
$path .= preg_replace('/[^a-zA-Z0-9]/','-',$mm['nodes'][ $mm['root_id'] ]['title']);
|
|
|
|
|
|
2023-02-07 20:16:39 +01:00
|
|
|
|
$new_name = magic_readline($mm, (empty($mm['filename']) ? $path : $mm['filename'] ) );
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 20:00:40 +02:00
|
|
|
|
if ($new_name === false)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
display($mm);
|
|
|
|
|
message($mm, 'Saving cancelled');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 20:00:40 +02:00
|
|
|
|
$mm['filename'] = $new_name;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$ext = mb_substr( $mm['filename'], mb_strrpos($mm['filename'],'.') + 1);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($ext!='hmm')
|
|
|
|
|
$mm['filename'] .= '.hmm';
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
display($mm);
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if (file_exists($mm['filename']) && !is_writable($mm['filename']))
|
|
|
|
|
{
|
|
|
|
|
message($mm, "ERROR! I don't have access to write into \"$mm[filename]\". Use shift+s and set another path and filename.");
|
|
|
|
|
sleep(1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-02-07 20:12:50 +01:00
|
|
|
|
change_window_title($mm['filename']);
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$file = fopen($mm['filename'], "w");
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['modified'] = false;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($file===false)
|
|
|
|
|
{
|
|
|
|
|
message($mm, 'ERROR! Could not save the file');
|
|
|
|
|
$mm['modified'] = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-02-10 09:53:54 +01:00
|
|
|
|
fwrite($file, map_to_list($mm, $mm['root_id']) . "\n");
|
2022-09-04 19:05:06 +02:00
|
|
|
|
fclose($file);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
display($mm);
|
2023-07-23 11:22:48 +02:00
|
|
|
|
if (!$mm['auto_save'])
|
|
|
|
|
message($mm, 'Saved '.$mm['filename']);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ message
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function message(&$mm, $text)
|
|
|
|
|
{
|
2022-09-23 11:11:16 +02:00
|
|
|
|
$mm['terminal_width'] = (int)exec('tput cols');
|
|
|
|
|
$mm['terminal_height'] = (int)exec('tput lines');
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
echo
|
|
|
|
|
"\033["
|
|
|
|
|
.$mm['terminal_height'] // y
|
|
|
|
|
.";"
|
2022-09-23 11:11:16 +02:00
|
|
|
|
.max(0,$mm['terminal_width'] - mb_strlen($text) - 1) //x
|
2022-09-19 20:33:27 +02:00
|
|
|
|
."f"
|
|
|
|
|
.$mm['message_color']
|
|
|
|
|
.' '
|
|
|
|
|
.$text
|
|
|
|
|
.' '
|
|
|
|
|
.reset_color
|
|
|
|
|
;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
usleep(200000);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ quit
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function quit()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
2023-07-23 11:22:48 +02:00
|
|
|
|
if (($mm['modified'] ?? false) === false)
|
|
|
|
|
shutdown();
|
2022-09-04 19:05:06 +02:00
|
|
|
|
message($mm, "You have unsaved changes. Save them, or use shift+Q to quit without saving.");
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-03-30 19:06:41 +01:00
|
|
|
|
function quit_with_debug()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
$file = fopen('./h-m-m--debug.txt', "w");
|
|
|
|
|
|
|
|
|
|
if ($file!==false)
|
|
|
|
|
{
|
|
|
|
|
fwrite($file, serialize($mm));
|
|
|
|
|
fclose($file);
|
|
|
|
|
echo "Debug information is written to h-m-m--debug.txt file.";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shutdown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ move_window
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function move_window(&$mm)
|
|
|
|
|
{
|
|
|
|
|
$node = $mm['nodes'][ $mm['active_node'] ];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$x1 = max(0, $node['x'] - conn_right_len - 2);
|
|
|
|
|
$x2 = $node['x'] + $node['w'] + 2;
|
|
|
|
|
$y1 = max(0, $node['y'] + $node['yo'] - vertical_offset);
|
|
|
|
|
$y2 = $y1 + $node['lh'] + vertical_offset*2;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['viewport_left'] = min( $mm['viewport_left'], $x1);
|
|
|
|
|
$mm['viewport_left'] = max( $mm['viewport_left'], $x2 - $mm['terminal_width']);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['viewport_top'] = min( $mm['viewport_top'], $y1);
|
|
|
|
|
$mm['viewport_top'] = max( $mm['viewport_top'], $y2 - $mm['terminal_height']);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-16 02:50:35 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ changes
|
|
|
|
|
|
|
|
|
|
function push_change(&$mm)
|
|
|
|
|
{
|
|
|
|
|
// flush any redo chain
|
|
|
|
|
while(count($mm['changes']) > $mm['change_index'])
|
2022-09-16 19:33:55 +02:00
|
|
|
|
{
|
2022-09-16 02:50:35 +02:00
|
|
|
|
array_pop($mm['changes']);
|
2022-09-16 19:33:55 +02:00
|
|
|
|
array_pop($mm['change_active_node']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// removing the old history if it's getting bigger than the maximum
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if (count($mm['changes']) >= $mm['max_undo_steps'])
|
2022-09-16 19:33:55 +02:00
|
|
|
|
{
|
|
|
|
|
array_shift($mm['changes']);
|
|
|
|
|
array_shift($mm['change_active_node']);
|
|
|
|
|
$mm['change_index']--;
|
|
|
|
|
}
|
2022-09-16 02:50:35 +02:00
|
|
|
|
|
|
|
|
|
array_push($mm['changes'], $mm['nodes']);
|
|
|
|
|
array_push($mm['change_active_node'], $mm['active_node']);
|
|
|
|
|
$mm['change_index']++;
|
2023-07-23 11:22:48 +02:00
|
|
|
|
|
|
|
|
|
$mm['modified'] = true;
|
|
|
|
|
if ($mm['auto_save'])
|
|
|
|
|
save_vh($mm);
|
2022-09-16 02:50:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function undo()
|
2022-09-16 02:50:35 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-16 02:50:35 +02:00
|
|
|
|
if($mm['change_index'] == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
$mm['change_index']--;
|
2022-09-21 16:20:01 +02:00
|
|
|
|
$mm['nodes'] = $mm['changes'][$mm['change_index']];
|
|
|
|
|
$mm['active_node'] = $mm['change_active_node'][$mm['change_index']];
|
2022-09-16 02:50:35 +02:00
|
|
|
|
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function redo()
|
2022-09-16 02:50:35 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-16 02:50:35 +02:00
|
|
|
|
if(count($mm['changes']) == $mm['change_index'])
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
$mm['nodes'] = $mm['changes'][$mm['change_index']];
|
|
|
|
|
$mm['active_node'] = $mm['change_active_node'][$mm['change_index']];
|
|
|
|
|
$mm['change_index']++;
|
|
|
|
|
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ change active node
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function change_active_node(&$mm, $x, $y)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
$node = $mm['nodes'][ $mm['active_node'] ];
|
|
|
|
|
|
|
|
|
|
// we go to the child that is closest to the parent node;
|
|
|
|
|
// i.e., closest to the middle.
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($x > 0)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-03-18 08:44:43 +01:00
|
|
|
|
if (count($node['visible_children'])==0)
|
|
|
|
|
return;
|
2022-09-16 12:49:26 +02:00
|
|
|
|
|
|
|
|
|
// auto-unfold node on right move
|
|
|
|
|
if ($node['collapsed'] ?? false) {
|
2022-09-19 20:33:27 +02:00
|
|
|
|
toggle_node($mm);
|
2022-09-16 12:49:26 +02:00
|
|
|
|
$node = $mm['nodes'][ $mm['active_node'] ];
|
|
|
|
|
}
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
$distance = [];
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($node['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$distance[$cid] =
|
|
|
|
|
abs
|
|
|
|
|
(
|
|
|
|
|
+ $node['y']
|
|
|
|
|
+ $node['yo']
|
|
|
|
|
+ $node['lh']/2
|
|
|
|
|
- $mm['nodes'][$cid]['y']
|
|
|
|
|
- $mm['nodes'][$cid]['yo']
|
|
|
|
|
- $mm['nodes'][$cid]['lh']/2
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
asort($distance);
|
|
|
|
|
|
|
|
|
|
$mm['active_node'] = array_keys($distance)[0];
|
|
|
|
|
|
|
|
|
|
display($mm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// no other movement applies to the root element
|
|
|
|
|
if ( $mm['active_node']==0 ) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// it can't be easier than moving to the left!
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($x < 0)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($mm['active_node']==$mm['root_id']) return;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['active_node'] = $node['parent'];
|
|
|
|
|
display($mm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// for up and down, we'll try to move between siblings first,
|
|
|
|
|
// considering that their order is set based on their list
|
|
|
|
|
// in the parent item.
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($y < 0)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$rchildren = array_reverse($mm['nodes'][ $node['parent'] ]['visible_children']);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($rchildren as $cid)
|
|
|
|
|
if ($mm['nodes'][$cid]['y']+$mm['nodes'][$cid]['yo'] < $node['y']+$node['yo'])
|
|
|
|
|
{
|
|
|
|
|
$mm['active_node'] = $cid;
|
|
|
|
|
display($mm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($y > 0)
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($mm['nodes'][ $node['parent'] ]['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($mm['nodes'][$cid]['y']+$mm['nodes'][$cid]['yo'] > $node['y']+$node['yo'])
|
|
|
|
|
{
|
|
|
|
|
$mm['active_node'] = $cid;
|
|
|
|
|
display($mm);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if it's not possible to move up or down between siblings,
|
|
|
|
|
// we'll measure distance and move to the nearest node.
|
|
|
|
|
// because the goal is to move vertically, and also because
|
|
|
|
|
// the aspect ratio of characters is not 1, there's a factor
|
|
|
|
|
// for y to give it more importance. I've set the amount by
|
|
|
|
|
// trial and erros and doesn't follow an exact logic. It may
|
|
|
|
|
// need refinements in the future.
|
|
|
|
|
|
|
|
|
|
$distance = [];
|
|
|
|
|
|
|
|
|
|
foreach ($mm['nodes'] as $id=>$nd)
|
|
|
|
|
if ($id != $mm['active_node'] && $nd['y']!=-1)
|
|
|
|
|
{
|
|
|
|
|
$dy = $nd['y'] + $nd['yo'] + $nd['lh']/2 - $node['y'] - $node['yo'] - $node['lh']/2;
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ( ($y>0 && $dy>0) || ($y<0 && $dy<0) )
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
$dx = $nd['x'] + $nd['w']/2 - $node['x'] - $node['w']/2;
|
|
|
|
|
$distance[$id] = pow($dy*15,2) + pow($dx,2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($distance==[]) return;
|
|
|
|
|
asort($distance);
|
|
|
|
|
|
|
|
|
|
$mm['active_node'] = array_keys($distance)[0];
|
|
|
|
|
|
|
|
|
|
display($mm);
|
|
|
|
|
return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-02 09:16:02 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ append
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function append()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] .=
|
2022-09-16 14:37:56 +02:00
|
|
|
|
' '
|
|
|
|
|
.str_replace
|
|
|
|
|
(
|
|
|
|
|
["\n","\r","\t"]
|
|
|
|
|
,[' ','', ' ']
|
|
|
|
|
,trim(get_from_clipboard($mm))
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
2022-09-02 09:16:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ paste sub-tree
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function paste_as_children()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
paste_sub_tree($mm, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function paste_as_siblings()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
paste_sub_tree($mm, true);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function paste_sub_tree(&$mm, $as_sibling )
|
|
|
|
|
{
|
2023-07-02 16:27:30 +02:00
|
|
|
|
if ($as_sibling && $mm['active_node']==$mm['root_id'])
|
|
|
|
|
return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($as_sibling)
|
|
|
|
|
$parent_id = $mm['nodes'][ $mm['active_node'] ]['parent'];
|
|
|
|
|
else
|
|
|
|
|
$parent_id = $mm['active_node'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
$mm['nodes'][ $parent_id ]['collapsed'] = false;
|
|
|
|
|
$mm['nodes'][ $parent_id ]['is_leaf'] = false;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$new_id = 1 + max(array_keys($mm['nodes']));
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-20 20:49:23 +02:00
|
|
|
|
// \n instead of PHP_EOL, just to be sure.
|
|
|
|
|
// existing \r's will be removed later.
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$st =
|
2022-09-19 20:33:27 +02:00
|
|
|
|
list_to_map
|
2022-09-04 19:05:06 +02:00
|
|
|
|
(
|
2022-09-15 09:51:32 +02:00
|
|
|
|
explode("\n",get_from_clipboard($mm)),
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$parent_id,
|
|
|
|
|
$new_id
|
|
|
|
|
)
|
|
|
|
|
;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-02 16:27:30 +02:00
|
|
|
|
if ($st==[])
|
|
|
|
|
return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 21:09:16 +02:00
|
|
|
|
push_change($mm);
|
|
|
|
|
|
|
|
|
|
$mm['nodes'] += $st;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
// doing it like this, in case the sub-tree has more than
|
|
|
|
|
// one top-level element.
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($st as $cid=>$cdata)
|
|
|
|
|
if ($cdata['parent'] == $parent_id)
|
|
|
|
|
$mm['nodes'][ $parent_id ]['children'][] = $cid;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
// rearranging the items only if they are pasted as siblings
|
|
|
|
|
// (for pasting as children, it makes sense to have them
|
|
|
|
|
// at the end)
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($as_sibling)
|
|
|
|
|
{
|
|
|
|
|
$sub_roots = [];
|
|
|
|
|
foreach ($st as $cid=>$cdata)
|
|
|
|
|
if ($cdata['parent']==$parent_id)
|
|
|
|
|
$sub_roots[] = $cid;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$children = [];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($mm['nodes'][ $parent_id ]['children'] as $child_id)
|
|
|
|
|
{
|
|
|
|
|
if (!in_array($child_id, $sub_roots))
|
|
|
|
|
$children[] = $child_id;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($child_id == $mm['active_node'])
|
|
|
|
|
$children = array_merge($children, $sub_roots);
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][ $parent_id ]['children'] = $children;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['active_node'] = $new_id;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ clipboard
|
|
|
|
|
|
2022-09-15 09:51:32 +02:00
|
|
|
|
function copy_to_clipboard(&$mm, $text)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-26 17:09:45 +02:00
|
|
|
|
switch ($mm['clipboard'])
|
|
|
|
|
{
|
|
|
|
|
case 'os':
|
|
|
|
|
$clip = popen($mm['os_clipboard']['write'],'wb');
|
2023-12-04 06:43:00 +01:00
|
|
|
|
if (!isset($clip))
|
|
|
|
|
return;
|
2022-09-26 17:09:45 +02:00
|
|
|
|
fwrite($clip,$text);
|
|
|
|
|
pclose($clip);
|
|
|
|
|
break;
|
|
|
|
|
case 'internal':
|
|
|
|
|
$GLOBALS['clipboard'] = $text;
|
|
|
|
|
break;
|
|
|
|
|
case 'file':
|
|
|
|
|
file_put_contents($mm['clipboard_file'],$text);
|
|
|
|
|
break;
|
|
|
|
|
case 'command':
|
|
|
|
|
shell_exec(str_replace('%text%', '"'.$text.'"', $mm['clipboard_in_command']));
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2022-09-15 09:51:32 +02:00
|
|
|
|
function get_from_clipboard(&$mm)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-26 17:09:45 +02:00
|
|
|
|
|
|
|
|
|
$text = 'clipboard unavailable!';
|
|
|
|
|
|
|
|
|
|
switch ($mm['clipboard'])
|
|
|
|
|
{
|
|
|
|
|
case 'os': $text = shell_exec($mm['os_clipboard']['read']); break;
|
|
|
|
|
case 'internal': $text = $GLOBALS['clipboard']; break;
|
|
|
|
|
case 'file': $text = file_get_contents($mm['clipboard_file']); break;
|
|
|
|
|
case 'command': $text = shell_exec($mm['clipboard_out_command']); break;
|
|
|
|
|
default: $text = "The clipboard type you've set is invalid!";
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
return
|
2022-09-16 14:37:56 +02:00
|
|
|
|
mb_ereg_replace
|
|
|
|
|
(
|
2022-09-17 00:41:45 +02:00
|
|
|
|
"[\000-\010\013-\037\177]|".BOM
|
2022-09-16 14:37:56 +02:00
|
|
|
|
,''
|
2022-09-26 17:09:45 +02:00
|
|
|
|
,$text
|
2022-09-16 14:37:56 +02:00
|
|
|
|
)
|
|
|
|
|
;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ load empty map
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function load_empty_map(&$mm)
|
|
|
|
|
{
|
2023-02-07 20:12:50 +01:00
|
|
|
|
change_window_title('new mind map');
|
|
|
|
|
|
2022-09-20 11:38:06 +02:00
|
|
|
|
if (isset($mm['nodes']))
|
|
|
|
|
unset($mm['nodes']);
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][0] =
|
|
|
|
|
[
|
|
|
|
|
'title'=>'X'
|
|
|
|
|
,'is_leaf'=>false
|
|
|
|
|
,'children'=>[1]
|
|
|
|
|
,'collapsed'=>false
|
|
|
|
|
,'parent'=>-1
|
|
|
|
|
]
|
|
|
|
|
;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-04-20 08:50:00 +02:00
|
|
|
|
$title = basename( empty($mm['filename']) ? 'root' : $mm['filename'] );
|
2023-04-19 17:22:49 +02:00
|
|
|
|
if (substr($title,-4)=='.hmm')
|
|
|
|
|
$title = substr($title,0,-4);
|
|
|
|
|
|
2022-09-20 11:38:06 +02:00
|
|
|
|
$mm['nodes'][1] =
|
|
|
|
|
[
|
2023-04-19 17:22:49 +02:00
|
|
|
|
'title'=> $title
|
2022-09-20 11:38:06 +02:00
|
|
|
|
,'is_leaf'=>true
|
|
|
|
|
,'children'=>[]
|
|
|
|
|
,'collapsed'=>false
|
|
|
|
|
,'parent'=>0
|
|
|
|
|
]
|
|
|
|
|
;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['active_node']=1;
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['root_id']=1;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ yank
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function yank_node()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
copy_to_clipboard($mm, map_to_list($mm, $mm['active_node'], false));
|
|
|
|
|
message($mm, 'Item(s) are copied to the clipboard.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function yank_children()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
copy_to_clipboard($mm, map_to_list($mm, $mm['active_node'], true));
|
2022-09-04 19:05:06 +02:00
|
|
|
|
message($mm, 'Item(s) are copied to the clipboard.');
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ delete
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function delete_node()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
delete_node_vh($mm, false, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function delete_children()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
delete_node_vh($mm, true, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function delete_node_without_clipboard()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
delete_node_vh($mm, false, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function delete_node_vh(&$mm, $exclude_parent = false, $dont_copy_to_clipboard = false )
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($mm['active_node']==$mm['root_id'])
|
2022-09-16 21:03:12 +02:00
|
|
|
|
$exclude_parent = true;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 21:03:12 +02:00
|
|
|
|
if (!$dont_copy_to_clipboard)
|
2022-09-19 20:33:27 +02:00
|
|
|
|
copy_to_clipboard($mm, map_to_list($mm, $mm['active_node'], $exclude_parent) );
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 19:33:55 +02:00
|
|
|
|
push_change($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
delete_node_internal($mm, $mm['active_node'], $exclude_parent);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-16 21:03:12 +02:00
|
|
|
|
if (!$dont_copy_to_clipboard)
|
|
|
|
|
message($mm, 'Item(s) are cut and placed into the clipboard.');
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function delete_node_internal(&$mm, $active_node, $exclude_parent = false )
|
|
|
|
|
{
|
|
|
|
|
// taking a shorter approach if it's for the whole tree
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($active_node==$mm['root_id'] && !$exclude_parent)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
load_empty_map($mm);
|
|
|
|
|
display($mm, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
// if it's for a sub-tree, then...
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
delete_children_vh($mm, $active_node);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($exclude_parent)
|
|
|
|
|
{
|
|
|
|
|
$mm['nodes'][ $active_node ]['is_leaf'] = true;
|
|
|
|
|
$mm['nodes'][ $active_node ]['children'] = [];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$parent_id = $mm['nodes'][ $active_node ]['parent'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$previous_sibling = 0;
|
|
|
|
|
$passed = false;
|
2023-03-17 20:24:17 +01:00
|
|
|
|
foreach ($mm['nodes'][$parent_id]['visible_children'] as $cid)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($cid==$active_node)
|
|
|
|
|
{
|
|
|
|
|
if ($previous_sibling!=0) break;
|
|
|
|
|
$passed = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$previous_sibling = $cid;
|
|
|
|
|
if ($passed) break;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][$parent_id]['children'] =
|
|
|
|
|
array_diff
|
|
|
|
|
(
|
|
|
|
|
$mm['nodes'][$parent_id]['children'],
|
|
|
|
|
[$active_node]
|
|
|
|
|
)
|
|
|
|
|
;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-18 10:21:18 +01:00
|
|
|
|
$mm['nodes'][$parent_id]['visible_children'] =
|
|
|
|
|
array_diff
|
|
|
|
|
(
|
|
|
|
|
$mm['nodes'][$parent_id]['visible_children'],
|
|
|
|
|
[$active_node]
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if (count($mm['nodes'][$parent_id]['children'])==0)
|
|
|
|
|
$mm['nodes'][$parent_id]['is_leaf'] = true;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
unset($mm['nodes'][ $active_node ]);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-03-17 20:24:17 +01:00
|
|
|
|
if (count($mm['nodes'][$parent_id]['visible_children'])==0)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['active_node'] = $parent_id;
|
|
|
|
|
else
|
|
|
|
|
$mm['active_node'] = $previous_sibling;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function delete_children_vh(&$mm,$id)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
foreach (($mm['nodes'][$id]['children'] ?? []) as $cid)
|
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
delete_children_vh($mm, $cid);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
unset($mm['nodes'][$cid]);
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ focus
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function toggle_focus_lock()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['focus_lock'] = !$mm['focus_lock'];
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
message($mm, $mm['focus_lock'] ? 'Focus locked' : 'Focus unlocked');
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function focus()
|
|
|
|
|
{
|
|
|
|
|
global $mm;
|
|
|
|
|
focus_vh($mm);
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm,true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function focus_vh(&$mm)
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
collapse_siblings($mm, $mm['active_node']);
|
|
|
|
|
expand_siblings($mm, $mm['active_node']);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|
2023-03-17 20:04:49 +01:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ collapse and expand
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function expand_all()
|
2023-03-17 20:04:49 +01:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
2023-03-17 20:04:49 +01:00
|
|
|
|
foreach ($mm['nodes'] as $id=>$node)
|
|
|
|
|
$mm['nodes'][$id]['collapsed'] = false;
|
|
|
|
|
|
|
|
|
|
build_map($mm);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2023-03-17 20:04:49 +01:00
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function collapse_siblings(&$mm, $id)
|
|
|
|
|
{
|
2023-03-18 08:44:43 +01:00
|
|
|
|
if ($id <= $mm['root_id'])
|
|
|
|
|
return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$parent_id = $mm['nodes'][$id]['parent'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($mm['nodes'][$parent_id]['children'] as $cid)
|
|
|
|
|
if ($cid!=$id)
|
|
|
|
|
$mm['nodes'][$cid]['collapsed'] = true;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
collapse_siblings($mm, $parent_id);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function expand_siblings(&$mm, $id)
|
|
|
|
|
{
|
2023-03-18 08:44:43 +01:00
|
|
|
|
if ($mm['nodes'][$id]['is_leaf'])
|
|
|
|
|
return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][$id]['collapsed'] = false;
|
|
|
|
|
foreach ($mm['nodes'][$id]['children'] as $cid)
|
|
|
|
|
expand_siblings($mm, $cid);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function collapse_other_branches()
|
2022-09-10 01:18:32 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($mm['active_node'] == $mm['root_id'])
|
2022-09-10 01:18:32 +02:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
$branch = find_branch($mm, $mm['active_node']);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
foreach ($mm['nodes'][ $mm['root_id'] ]['children'] as $bid)
|
2022-09-10 01:18:32 +02:00
|
|
|
|
if ($bid != $branch)
|
|
|
|
|
$mm['nodes'][$bid]['collapsed'] = true;
|
|
|
|
|
|
|
|
|
|
build_map($mm);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2022-09-10 01:18:32 +02:00
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-13 11:45:03 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function collapse_inner()
|
2022-09-13 11:45:03 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-13 11:45:03 +02:00
|
|
|
|
foreach ($mm['nodes'][ $mm['active_node'] ]['children'] as $cid)
|
|
|
|
|
$mm['nodes'][$cid]['collapsed'] = true;
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['collapsed'] = false;
|
|
|
|
|
|
|
|
|
|
build_map($mm);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2022-09-13 11:45:03 +02:00
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-10 01:18:32 +02:00
|
|
|
|
function find_branch(&$mm, $cid)
|
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if ($mm['nodes'][$cid]['parent'] == $mm['root_id'])
|
2022-09-10 01:18:32 +02:00
|
|
|
|
return $cid;
|
|
|
|
|
else
|
|
|
|
|
return find_branch($mm, $mm['nodes'][$cid]['parent']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function collapse_all()
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
foreach ($mm['nodes'] as $id=>$node)
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if (!$node['is_leaf'] && $id!=0 && $id!=$mm['root_id'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['nodes'][$id]['collapsed'] = true;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['active_node'] = $mm['root_id'];
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2022-09-04 19:05:06 +02:00
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function collapse_children()
|
2022-12-31 22:48:16 +01:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2022-12-31 22:48:16 +01:00
|
|
|
|
foreach ($mm['nodes'][ $mm['active_node'] ]['children'] as $cid)
|
|
|
|
|
if (!$mm['nodes'][$cid]['is_leaf'])
|
|
|
|
|
$mm['nodes'][$cid]['collapsed'] = true;
|
|
|
|
|
|
|
|
|
|
build_map($mm);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2022-12-31 22:48:16 +01:00
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function collapse(&$mm, $id, $keep)
|
|
|
|
|
{
|
|
|
|
|
if ($mm['nodes'][$id]['is_leaf']) return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($keep<=0)
|
|
|
|
|
$mm['nodes'][$id]['collapsed'] = true;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
$mm['nodes'][$id]['collapsed'] = false;
|
|
|
|
|
foreach ($mm['nodes'][$id]['children'] as $cid)
|
|
|
|
|
collapse($mm, $cid, $keep-1);
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function collapse_level_1() { global $mm; collapse_level($mm, 1); }
|
|
|
|
|
function collapse_level_2() { global $mm; collapse_level($mm, 2); }
|
|
|
|
|
function collapse_level_3() { global $mm; collapse_level($mm, 3); }
|
|
|
|
|
function collapse_level_4() { global $mm; collapse_level($mm, 4); }
|
|
|
|
|
function collapse_level_5() { global $mm; collapse_level($mm, 5); }
|
|
|
|
|
function collapse_level_6() { global $mm; collapse_level($mm, 6); }
|
|
|
|
|
function collapse_level_7() { global $mm; collapse_level($mm, 7); }
|
|
|
|
|
function collapse_level_8() { global $mm; collapse_level($mm, 8); }
|
|
|
|
|
function collapse_level_9() { global $mm; collapse_level($mm, 9); }
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function collapse_level(&$mm, $level, $no_display = false)
|
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
collapse($mm, $mm['root_id'], $level);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$id_collapsed = [];
|
|
|
|
|
$current = $mm['active_node'];
|
2022-09-19 20:33:27 +02:00
|
|
|
|
while ($current != $mm['root_id'])
|
2022-09-04 19:05:06 +02:00
|
|
|
|
{
|
|
|
|
|
$id_collapsed[$current] = $mm['nodes'][$current]['collapsed'];
|
|
|
|
|
$current = $mm['nodes'][$current]['parent'];
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$id_collapsed = array_reverse( $id_collapsed, true);
|
|
|
|
|
foreach ($id_collapsed as $id=>$collapsed)
|
|
|
|
|
if ($collapsed)
|
|
|
|
|
{
|
|
|
|
|
$mm['active_node'] = $id;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
if ($no_display) return;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2022-09-04 19:05:06 +02:00
|
|
|
|
display($mm);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
// {{{ display
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function display(&$mm, $force_center = false)
|
|
|
|
|
{
|
|
|
|
|
if ($mm['focus_lock'])
|
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
focus_vh($mm);
|
2022-09-04 19:05:06 +02:00
|
|
|
|
build_map($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($mm['center_lock'] || $force_center)
|
2023-07-23 10:45:10 +02:00
|
|
|
|
center_active_node_vh();
|
2022-09-04 19:05:06 +02:00
|
|
|
|
else
|
|
|
|
|
move_window($mm);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['terminal_width'] = (int)exec('tput cols');
|
|
|
|
|
$mm['terminal_height'] = (int)exec('tput lines');
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
$blank = str_repeat(' ', $mm['terminal_width']);
|
|
|
|
|
|
2023-02-05 18:22:33 +01:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
// calculating the coordinates of the active node
|
|
|
|
|
|
|
|
|
|
$x1 =
|
|
|
|
|
max
|
|
|
|
|
(
|
|
|
|
|
0
|
|
|
|
|
,$mm['nodes'][ $mm['active_node'] ]['x']
|
|
|
|
|
-1
|
2022-09-19 20:33:27 +02:00
|
|
|
|
-$mm['viewport_left']
|
2022-09-04 19:05:06 +02:00
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$x2
|
2022-09-04 19:05:06 +02:00
|
|
|
|
= $mm['nodes'][ $mm['active_node'] ]['w']
|
|
|
|
|
+ $x1
|
|
|
|
|
+ 2
|
|
|
|
|
- ($mm['active_node']==0 && left_padding==0)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
$y1 =
|
|
|
|
|
max
|
|
|
|
|
(
|
|
|
|
|
0
|
|
|
|
|
, $mm['nodes'][ $mm['active_node'] ]['y']
|
|
|
|
|
+ $mm['nodes'][ $mm['active_node'] ]['yo']
|
2022-09-19 20:33:27 +02:00
|
|
|
|
- $mm['viewport_top']
|
2022-09-04 19:05:06 +02:00
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$y2
|
2022-09-04 19:05:06 +02:00
|
|
|
|
= $mm['nodes'][ $mm['active_node'] ]['lh']
|
|
|
|
|
+ $y1
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
// building the output
|
|
|
|
|
|
|
|
|
|
$output = '';
|
|
|
|
|
|
|
|
|
|
for ( $y = 0 ; $y < $mm['terminal_height'] ; $y++ )
|
|
|
|
|
{
|
2022-09-19 20:33:27 +02:00
|
|
|
|
if (isset($mm['map'][$y+$mm['viewport_top']]))
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$line =
|
|
|
|
|
mb_substr(
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$mm['map'][$y+$mm['viewport_top']],
|
|
|
|
|
$mm['viewport_left'],
|
2022-09-04 19:05:06 +02:00
|
|
|
|
$mm['terminal_width']
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
else
|
|
|
|
|
$line = $blank;
|
|
|
|
|
|
|
|
|
|
// this one really depends on (x,y), but after this, the
|
|
|
|
|
// coordinates are not reliable anymore because of the
|
|
|
|
|
// added escape codes.
|
|
|
|
|
|
|
|
|
|
if ( $y >= $y1 && $y < $y2 )
|
|
|
|
|
$line =
|
|
|
|
|
mb_substr($line, 0, $x1)
|
|
|
|
|
.$mm['active_node_color']
|
|
|
|
|
.mb_substr($line, $x1, $x2-$x1)
|
|
|
|
|
.reset_color
|
|
|
|
|
.mb_substr($line, $x2)
|
|
|
|
|
;
|
2023-01-07 12:39:31 +01:00
|
|
|
|
|
|
|
|
|
// styling the codes when the node is not active
|
2023-04-20 11:03:48 +02:00
|
|
|
|
// with "else", the downside is that other codes
|
|
|
|
|
// with the same "y" will not be styled.
|
|
|
|
|
// Without the "else", the downside is that the
|
|
|
|
|
// rest of the line in the active node won't be bold.
|
|
|
|
|
// between these two, I think the former is better.
|
2023-01-07 12:39:31 +01:00
|
|
|
|
|
2023-04-20 11:03:48 +02:00
|
|
|
|
else
|
|
|
|
|
$line =
|
|
|
|
|
mb_ereg_replace
|
|
|
|
|
(
|
|
|
|
|
'\b(.?\d+)\. '
|
|
|
|
|
,dim_on.'\\1. '.dim_off
|
|
|
|
|
,$line
|
|
|
|
|
)
|
|
|
|
|
;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
2022-09-10 10:59:22 +02:00
|
|
|
|
// styling the search results
|
2022-09-04 19:05:06 +02:00
|
|
|
|
|
|
|
|
|
if ($mm['query'] ?? '' != '')
|
|
|
|
|
$line =
|
|
|
|
|
str_ireplace
|
|
|
|
|
(
|
|
|
|
|
$mm['query']
|
|
|
|
|
,invert_on.$mm['query'].invert_off
|
|
|
|
|
,$line
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
// styling the collapsed symbol
|
|
|
|
|
|
|
|
|
|
$line =
|
|
|
|
|
str_replace
|
|
|
|
|
(
|
|
|
|
|
' [+]'
|
|
|
|
|
,' '
|
|
|
|
|
.collapsed_symbol_on
|
|
|
|
|
.'[+]'
|
|
|
|
|
.collapsed_symbol_off
|
|
|
|
|
,$line
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
// styling the lines
|
|
|
|
|
|
|
|
|
|
$line =
|
|
|
|
|
mb_ereg_replace
|
|
|
|
|
(
|
2022-09-09 21:35:23 +02:00
|
|
|
|
'([─-╱]+)'
|
2022-09-04 19:05:06 +02:00
|
|
|
|
,line_on.'\\1'.line_off
|
|
|
|
|
,$line
|
|
|
|
|
)
|
|
|
|
|
;
|
|
|
|
|
|
2023-07-23 16:57:17 +02:00
|
|
|
|
// styling "(?)
|
|
|
|
|
|
|
|
|
|
$line =
|
|
|
|
|
str_replace
|
|
|
|
|
(
|
|
|
|
|
'(?)'
|
|
|
|
|
,$mm['doubt_color'].'(?)'.default_color
|
|
|
|
|
,$line
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-09 21:44:04 +02:00
|
|
|
|
// styling "???"
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$line =
|
2022-09-09 21:44:04 +02:00
|
|
|
|
str_replace
|
|
|
|
|
(
|
|
|
|
|
'???'
|
2022-09-19 20:33:27 +02:00
|
|
|
|
,$mm['doubt_color'].'???'.default_color
|
2022-09-09 21:44:04 +02:00
|
|
|
|
,$line
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-09 21:35:23 +02:00
|
|
|
|
// dimming {meta}s
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$line =
|
2022-09-09 21:35:23 +02:00
|
|
|
|
str_replace
|
|
|
|
|
(
|
|
|
|
|
'{'
|
|
|
|
|
,dim_on.'{'
|
|
|
|
|
,$line
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
$line =
|
2022-09-09 21:35:23 +02:00
|
|
|
|
str_replace
|
|
|
|
|
(
|
|
|
|
|
'}'
|
|
|
|
|
,'}'.dim_off
|
|
|
|
|
,$line
|
|
|
|
|
);
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
// done!
|
|
|
|
|
$output .= $line;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-05 18:22:33 +01:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
echo reset_page.reset_color.$output;
|
2023-02-05 18:22:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// showing the logo :)
|
|
|
|
|
|
|
|
|
|
if ($mm['show_logo'])
|
|
|
|
|
{
|
|
|
|
|
$ll = $mm['terminal_width'] - 14;
|
2023-12-04 06:24:43 +01:00
|
|
|
|
echo "\033[1;{$ll}f\033[38;5;237m ┌────────────┐ ";
|
|
|
|
|
echo "\033[2;{$ll}f\033[38;5;237m │ ╭─ m │ ";
|
|
|
|
|
echo "\033[3;{$ll}f\033[38;5;237m │ h ──┤ │ ";
|
|
|
|
|
echo "\033[4;{$ll}f\033[38;5;237m │ ╰─── m │ ";
|
|
|
|
|
echo "\033[5;{$ll}f\033[38;5;237m └────────────┘ ";
|
2023-02-05 18:22:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
function mmput(&$mm,$x,$y,$s)
|
|
|
|
|
{
|
|
|
|
|
$y = round($y);
|
|
|
|
|
|
|
|
|
|
$mm['map'][$y]
|
|
|
|
|
= mb_substr( $mm['map'][$y], 0, $x)
|
|
|
|
|
. $s
|
|
|
|
|
. mb_substr( $mm['map'][$y], $x + mb_strlen($s) );
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-04 10:55:44 +02:00
|
|
|
|
function mmputcontent(&$mm,$x,$y,$s)
|
|
|
|
|
{
|
|
|
|
|
$y = round($y);
|
|
|
|
|
|
|
|
|
|
$mm['map'][$y]
|
|
|
|
|
= mb_substr( $mm['map'][$y], 0, $x)
|
|
|
|
|
. $s
|
|
|
|
|
. mb_substr( $mm['map'][$y], $x + mb_strwidth($s) );
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
|
2022-12-22 17:07:30 +01:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ rank
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function increase_positive_rank() { global $mm; rank($mm, +1, 0); }
|
|
|
|
|
function decrease_positive_rank() { global $mm; rank($mm, -1, 0); }
|
|
|
|
|
function increase_negative_rank() { global $mm; rank($mm, 0, +1); }
|
|
|
|
|
function decrease_negative_rank() { global $mm; rank($mm, 0, -1); }
|
|
|
|
|
|
2022-12-22 17:07:30 +01:00
|
|
|
|
function rank(&$mm, $add_positive, $add_negative)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
$negative = 0;
|
|
|
|
|
$positive = 0;
|
|
|
|
|
$existing = [];
|
|
|
|
|
|
|
|
|
|
if (mb_ereg('^\((\d+)\+,(\d+)\-\)', $mm['nodes'][ $mm['active_node'] ]['title'], $existing))
|
|
|
|
|
{
|
|
|
|
|
$positive = $existing[1];
|
|
|
|
|
$negative = $existing[2];
|
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] =
|
|
|
|
|
mb_ereg_replace('^\(\d+\+,\d+\-\) *', '', $mm['nodes'][ $mm['active_node'] ]['title']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$negative = max(0, $negative + $add_negative);
|
|
|
|
|
$positive = max(0, $positive + $add_positive);
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][ $mm['active_node'] ]['title'] =
|
|
|
|
|
"({$positive}+,{$negative}-) "
|
|
|
|
|
.$mm['nodes'][ $mm['active_node'] ]['title']
|
|
|
|
|
;
|
|
|
|
|
|
2023-01-01 11:14:54 +01:00
|
|
|
|
push_change($mm);
|
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-04-19 17:58:56 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ open link
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function open_link()
|
2023-04-19 17:58:56 +02:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
2023-04-19 17:58:56 +02:00
|
|
|
|
message($mm,'Opening the node with xdg-open...');
|
|
|
|
|
exec('xdg-open "'.$mm['nodes'][ $mm['active_node'] ]['title'].'" >/dev/null 2>&1 &', $output, $result);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-01-01 11:14:54 +01:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ sort
|
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
function sort_siblings()
|
2023-01-01 11:14:54 +01:00
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $mm;
|
|
|
|
|
|
2023-01-01 11:14:54 +01:00
|
|
|
|
if ($mm['active_node'] <= $mm['root_id'])
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
$siblings = [];
|
|
|
|
|
$sibling_ids = $mm['nodes'][ $mm['nodes'][ $mm['active_node'] ]['parent'] ]['children'];
|
|
|
|
|
|
|
|
|
|
if (empty($sibling_ids))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
foreach ($sibling_ids as $sid)
|
|
|
|
|
if (mb_ereg('^\((\d+)\+,(\d+)\-\)', $mm['nodes'][$sid]['title'], $values))
|
2023-03-18 08:34:00 +01:00
|
|
|
|
$siblings
|
|
|
|
|
[
|
|
|
|
|
(9000000 - $values[1] + $values[2])
|
|
|
|
|
.'.'
|
2024-04-08 08:26:55 +02:00
|
|
|
|
.$sid
|
2023-03-18 08:34:00 +01:00
|
|
|
|
]
|
|
|
|
|
= $sid;
|
2023-01-01 11:14:54 +01:00
|
|
|
|
else
|
2023-03-18 08:34:00 +01:00
|
|
|
|
$siblings
|
|
|
|
|
[
|
|
|
|
|
mb_ereg_replace
|
|
|
|
|
(
|
|
|
|
|
'^\[HIDDEN\] |^'.$mm['symbol1'].' |^'.$mm['symbol2'].' '
|
|
|
|
|
,''
|
|
|
|
|
,$mm['nodes'][$sid]['title']
|
|
|
|
|
)
|
|
|
|
|
.'.'
|
|
|
|
|
.$sid
|
2024-04-08 08:26:55 +02:00
|
|
|
|
]
|
2023-03-18 08:34:00 +01:00
|
|
|
|
= $sid;
|
2023-01-01 11:14:54 +01:00
|
|
|
|
|
|
|
|
|
ksort($siblings, SORT_NATURAL);
|
|
|
|
|
|
|
|
|
|
$mm['nodes'][ $mm['nodes'][ $mm['active_node'] ]['parent'] ]['children'] = $siblings;
|
|
|
|
|
|
|
|
|
|
push_change($mm);
|
2022-12-22 17:07:30 +01:00
|
|
|
|
build_map($mm);
|
|
|
|
|
display($mm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ monitor key presses
|
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
function monitor_key_presses(&$mm)
|
|
|
|
|
{
|
2023-07-23 10:45:10 +02:00
|
|
|
|
global $keybindings;
|
2022-09-04 19:05:06 +02:00
|
|
|
|
stream_set_blocking(STDIN,false);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2022-09-04 19:05:06 +02:00
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
|
usleep(20000);
|
|
|
|
|
$in = fread(STDIN, 16);
|
2023-03-26 14:25:36 +02:00
|
|
|
|
|
|
|
|
|
if (empty($in))
|
|
|
|
|
continue;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-23 10:45:10 +02:00
|
|
|
|
if (isset($keybindings[$in]))
|
|
|
|
|
call_user_func($keybindings[$in]);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-07-25 09:09:07 +02:00
|
|
|
|
if ($mm['echo_keys'])
|
|
|
|
|
{
|
|
|
|
|
echo "\033[1;1f";
|
|
|
|
|
for ($i=0; $i<strlen($in); $i++)
|
|
|
|
|
echo base_convert(ord($in[$i]),10,8).' ';
|
|
|
|
|
echo ' ';
|
|
|
|
|
}
|
2022-09-04 19:05:06 +02:00
|
|
|
|
}
|
2022-08-30 17:54:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-07 20:12:50 +01:00
|
|
|
|
// }}}
|
2023-02-07 20:21:56 +01:00
|
|
|
|
// {{{ change window title
|
2023-02-07 20:12:50 +01:00
|
|
|
|
|
|
|
|
|
function change_window_title($title)
|
|
|
|
|
{
|
2023-02-07 20:21:56 +01:00
|
|
|
|
echo "\033]2;".( $title == '' ? ' ' : 'h-m-m -- '.str_replace('.hmm','',basename($title)) )."\007";
|
2023-02-07 20:12:50 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-30 17:54:49 +02:00
|
|
|
|
// }}}
|
|
|
|
|
// {{{ main
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
check_required_extensions();
|
2022-09-15 09:51:32 +02:00
|
|
|
|
check_the_available_clipboard_tool($mm);
|
|
|
|
|
|
2022-09-19 20:33:27 +02:00
|
|
|
|
enable_alternate_screen();
|
2022-08-30 17:54:49 +02:00
|
|
|
|
load_file($mm);
|
|
|
|
|
|
2022-09-09 21:35:23 +02:00
|
|
|
|
collapse_all($mm);
|
2023-03-26 14:25:36 +02:00
|
|
|
|
collapse_level($mm, $mm['initial_depth'], false);
|
2022-08-30 17:54:49 +02:00
|
|
|
|
|
2023-12-04 06:24:43 +01:00
|
|
|
|
$mm['show_logo'] = false;
|
2022-08-30 17:54:49 +02:00
|
|
|
|
monitor_key_presses($mm);
|
|
|
|
|
|
|
|
|
|
// }}}
|
2022-09-18 13:48:51 +02:00
|
|
|
|
|