t-src 'none'
Content-Type: text/plain; charset=UTF-8
Content-Length: 8835
Content-Disposition: inline; filename="Embed.pm"
Last-Modified: Wed, 12 Feb 2025 12:40:27 GMT
Expires: Wed, 12 Feb 2025 12:45:27 GMT
ETag: "c033d3c931bdac669fee2bd22940d544f7ae5ed4"

package HexChat::Embed;
use strict;
use warnings;
use Data::Dumper;
# list of loaded scripts keyed by their package names
# The package names are generated from the filename of the script using
# the file2pkg() function.
# The values of this hash are hash references with the following keys:
#   filename
#     The full path to the script.
#   gui_entry
#     This is hexchat_plugin pointer that is used to remove the script from
#     Plugins and Scripts window when a script is unloaded. This has also
#     been converted with the PTR2IV() macro.
#   hooks
#     This is an array of hooks that are associated with this script.
#     These are pointers that have been converted with the PTR2IV() macro.
#   inner_packages
#     Other packages that are defined in a script. This is not recommended
#     partly because these will also get removed when a script is unloaded.
#   loaded_at
#     A timestamp of when the script was loaded. The value is whatever
#     Time::HiRes::time() returns. This is used to retain load order when
#     using the RELOADALL command.
#   shutdown
#     This is either a code ref or undef. It will be executed just before a
#     script is unloaded.
our %scripts;

# This is a mapping of "inner package" => "containing script package"
our %owner_package;

# used to keep track of which package a hook belongs to, if the normal way of
# checking which script is calling a hook function fails this will be used
# instead. When a hook is created this will be copied to the HookData structure
# and when a callback is invoked this it will be used to set this value.
our $current_package;

sub load {
	my $file = expand_homedir( shift @_ );
	my $package = file2pkg( $file );
	
	if( exists $scripts{$package} ) {
		my $pkg_info = pkg_info( $package );
		my $filename = File::Basename::basename( $pkg_info->{filename} );
		HexChat::printf(
			qq{'%s' already loaded from '%s'.\n},
			$filename, $pkg_info->{filename}
		);
		HexChat::print(
			'If this is a different script then it rename and try '.
			'loading it again.'
		);
		return 2;
	}
	
	if( open my $source_handle, $file ) {
		my $source = do {local $/; <$source_handle>};
		close $source_handle;
		# we shouldn't care about things after __END__
		$source =~ s/^__END__.*//ms;
		
		# this must come before the eval or the filename will not be found in
		# HexChat::register
		$scripts{$package}{filename} = $file;
		$scripts{$package}{loaded_at} = Time::HiRes::time();

		# this must be done before the error check so the unload will remove
		# any inner packages defined by the script. if a script fails to load
		# then any inner packages need to be removed as well.
		my @inner_packages = $source =~
			m/^\s*package \s+
				((?:[^\W:]+(?:::)?)+)\s*? # package name
				# strict version number
				(?:\d+(?:[.]\d+) # positive integer or decimal-fraction
					|v\d+(?:[.]\d+){2,})? # dotted-decimal v-string
				[{;]
			/mgx;

		# check if any inner package defined in the to be loaded script has
		# already been defined by another script
		my @conflicts;
		for my $inner ( @inner_packages ) {
			if( exists $owner_package{ $inner } ) {
				push @conflicts, $inner;
			}
		}

		# report conflicts and bail out
		if( @conflicts ) {
			my $error_message =
				"'$file' won't be loaded due to conflicting inner packages:\n";
			for my $conflict_package ( @conflicts ) {
				$error_message .= "   $conflict_package already defined in " .
					pkg_info($owner_package{ $conflict_package })->{filename}."\n";
			}
			HexChat::print( $error_message );

			return 2;
		}

		my $full_path = File::Spec->rel2abs( $file );
		$source =~ s/^/#line 1 "$full_path"\n\x7Bpackage $package;/;

		# make sure we add the closing } even if the last line is a comment
		if( $source =~ /^#.*\Z/m ) {
			$source =~ s/^(?=#.*\Z)/\x7D/m;
		} else {
			$source =~ s/\Z/\x7D/;
		}

		$scripts{$package}{inner_packages} = [ @inner_packages ];
		@owner_package{ @inner_packages } = ($package) x @inner_packages;
		_do_eval( $source );

		unless( exists $scripts{$package}{gui_entry} ) {
			$scripts{$package}{gui_entry} =
				HexChat::Internal::register(
					"", "unknown", "", $file
				);
		}

		if( $@ ) {
			# something went wrong
			$@ =~ s/\(eval \d+\)/$file/g;
			HexChat::print( "Error loading '$file':\n$@\n" );
			# make sure the script list doesn't contain false information
			unload( $scripts{$package}{filename} );
			return 1;
		}
	} else {
		HexChat::print( "Error opening '$file': $!\n" );
		return 2;
	}

	return 0;
}

sub _do_eval {
	no strict;
	no warnings;
	eval $_[0];
}

sub unload {
	my $file = shift @_;
	my $package = file2pkg( $file );
	my $pkg_info = pkg_info( $package );

	if<style>pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span>[Desktop Entry]
_Name=HexChat
_GenericName=IRC Client
_Comment=Chat with other people online
_Keywords=IM;Chat;
Exec=hexchat %U
Icon=hexchat
Terminal=false
Type=Application
Categories=GTK;Network;IRCClient;
StartupNotify=true
X-GNOME-UsesNotifications=true
MimeType=x-scheme-handler/irc;x-scheme-handler/ircs;
Actions=SafeMode;

[Desktop Action SafeMode]
_Name=Open Safe Mode
Exec=hexchat --no-auto --no-plugins
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.causal.agency/cgit-pink/about/'>cgit-pink 1.4.1</a> (<a href='https://git-scm.com/'>git 2.36.1</a>) at 2025-02-12 12:40:28 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
