Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

beebox / crossover   deb

Repository URL to install this package:

Version: 18.5.0-1 

/ opt / cxoffice / lib / perl / CXMenuCDE.pm

# (c) Copyright 2006, 2008, 2010, 2014. CodeWeavers, Inc.
package CXMenuCDE;
use warnings;
use strict;
use CXLog;
use CXUtils;
use CXMenu;
use base "CXMenu";
use CXCDE;


sub read_dt_file($)
{
    my ($self)=@_;
    if (!$self->{dtfile})
    {
        $self->{dtfile}=CXCDE->new("$self->{dtdir}/cxmenu-$self->{tag}.dt");
    }
    return ($self->{dtfile} ? 1 : 0);
}

sub detect($$$$)
{
    my ($class, $cxoptions, $cxconfig, $gui_info)=@_;
    return () if (!$gui_info->{cde_on});

    my $self={
        tag         => $cxoptions->{tag},
        destdir     => $cxoptions->{destdir},
        scope       => $gui_info->{preferred_scope},
        wmdir       => "$cxoptions->{destdir}$gui_info->{cde_preferred_wm}",
        dtdir       => "$cxoptions->{destdir}$gui_info->{cde_preferred_dt}",
    };

    if ($self->{scope} ne "managed")
    {
        $self->{dtaction}=CXUtils::cxwhich("$ENV{PATH}:/usr/dt/bin", "dtaction");
        if (!defined $self->{dtaction})
        {
            cxlog("unable to find 'dtaction'. Maybe you need to install the SUNWdtbas package?\n");
            return ();
        }
    }

    bless $self, $class;
    return ($self);
}

sub id($)
{
    my ($self)=@_;
    my $id="CXMenuCDE/$self->{wmdir}";
    $id =~ s%/+%/%g;
    return $id;
}

sub install($$)
{
    my ($self, $components)=@_;

    my $menu=$components->[-1];
    # We don't support desktop icons
    return 1 if ($menu->{is_desktop});
    return 0 if (!$self->read_dt_file());

    if ($self->{scope} ne "managed" and $self->{destdir} eq "" and
        !-d $self->{wmdir})
    {
        # Create ~/.dt/wsmenu and populate it with the global menus
        # Also updates ~/.dt/$LANG/wsmenu.dtwmrc but we don't care yet
        # Make sure we only run one instance at a time (just to be safe).
        my $lock=CXUtils::cxlock("cde");
        if (!-d $self->{wmdir} and
            cxsystem($self->{dtaction}, "BuildDtwmrcFromWsmenuDir"))
        {
            cxlog("unable to create '$self->{wmdir}'\n");
            CXUtils::cxunlock($lock);
            return 0;
        }
        CXUtils::cxunlock($lock);
    }

    my $dir=$self->{wmdir} . ($menu->{is_dir} ? $menu->{path} : $menu->{dir});
    if (!-d $dir)
    {
        foreach my $component (@$components)
        {
            last if (!$component->{is_dir});
            my $dir="$self->{wmdir}/$component->{path}";
            if (!cxmkpath($dir))
            {
                cxerr("unable to create the '$dir' directory: $@\n");
                return 0;
            }
        }
    }

    if ($menu->{is_dir})
    {
        # Make sure our brand new (maybe empty) folder will not be
        # 'garbage collected' by finalize()
        $self->{status}->{$menu->{path}}="in-use";
    }
    else
    {
        $self->{status}->{$menu->{dir}}="in-use";

        # Create a new action
        my $icon=CXMenu::get_unix_icon_path($menu) ||
                 CXMenu::get_default_icon_path(0);
        my $action={LABEL       => $menu->{name},
                    TYPE        => "COMMAND",
                    EXEC_STRING => $menu->{command},
                    ICON        => $icon,
                    WINDOW_TYPE => "NO_STDIO"
                   };
        my $mangled="cxmenu-$self->{tag}" . mangle_string($menu->{path});
        $self->{dtfile}->{actions}->{$mangled}=$action;
        $self->{modified}=1;

        # Reference that action in the Workspace Menu
        my $fh;
        if (!open($fh, ">", "$dir/$mangled"))
        {
            cxerr("unable to open '$dir/$mangled' for writing: $!\n");
            return 0;
        }
        print $fh "#!/bin/sh\n";
        print $fh "# X-Created-By=$mangled\n";
        print $fh "exec dtaction \"$mangled\" \"\$\@\"\n";
        close($fh);
        chmod(0777 & ~umask(), "$dir/$mangled");
    }

    return 1;
}

sub query($$)
{
    my ($self, $components)=@_;
    return ($self->id(), "") if (!defined $components);

    my $menu=$components->[-1];
    # We don't support desktop icons
    return "" if ($menu->{is_desktop});
    return 0 if (!$self->read_dt_file());

    if (!$menu->{is_dir})
    {
        my $mangled="cxmenu-$self->{tag}" . mangle_string($menu->{path});
        return "" if (!$self->{dtfile}->{actions}->{$mangled});
        my $filename="$self->{wmdir}$menu->{dir}/$mangled";
        return "" if (!-x $filename);
    }
    else
    {
        return "" if (!-d "$self->{wmdir}$menu->{path}");
    }
    return $self->id();
}

sub get_files($$)
{
    my ($self, $components)=@_;

    my $menu=$components->[-1];
    # We don't support desktop icons
    return [] if ($menu->{is_desktop} or !$self->read_dt_file());

    if (!$menu->{is_dir})
    {
        my $filename=$self->{wmdir} . $menu->{dir} . "cxmenu-$self->{tag}" . mangle_string($menu->{path});
        return [$filename] if (-f $filename);
    }
    return [];
}

sub uninstall($$)
{
    my ($self, $components)=@_;

    my $menu=$components->[-1];
    # We don't support desktop icons
    return 1 if ($menu->{is_desktop});
    return 0 if (!$self->read_dt_file());

    # Always mark the parent folder for garbage collection
    $self->{garbage_collect}->{$menu->{dir}}=1;

    # FIXME: We should also handle the is_dir case
    if (!$menu->{is_dir})
    {
        my $mangled="cxmenu-$self->{tag}" . mangle_string($menu->{path});
        delete $self->{dtfile}->{actions}->{$mangled};
        $self->{modified}=1;

        my $filename="$self->{wmdir}$menu->{dir}/$mangled";
        if (-f $filename)
        {
            cxlog("Deleting '$filename'\n");
            if (!unlink $filename)
            {
                cxerr("unable to delete '$filename': $1\n");
                return 0;
            }
        }
    }

    return 1;
}

# This function assumes that it is being called before any of the others
# which means it does not have to clean up 'filename', 'actions', etc.
sub removeall($$)
{
    my ($self, $pattern)=@_;

    my $dt_pattern;
    if ($pattern eq "legacy")
    {
        $dt_pattern="^" . CXUtils::get_product_id() . "\\..*\\.(?:dt|fp)\$";
    }
    else
    {
        $pattern.=".*" if ($pattern !~ s/\$$//);
        $dt_pattern="^cxmenu-$pattern\\.dt\$";
    }
    cxlog("dt_pattern=[$dt_pattern]\n");

    # Delete the dt file
    if (CXUtils::delete_files($self->{dtdir}, $dt_pattern) > 0)
    {
        $self->{update}=1;
    }

    # And the Workspace Menu files that refer to them
    $pattern="^cxmenu-${pattern}_";
    $dt_pattern.=".*" if ($dt_pattern !~ s/\$$//);
    cxlog("pattern=[$pattern]\n");
    my $rc=1;
    my @dirs=("");
    while (@dirs)
    {
        my $dir=shift @dirs;
        if (opendir(my $dh, "$self->{wmdir}$dir"))
        {
            cxlog("$dir\n");
            foreach my $dentry (readdir $dh)
            {
                next if ($dentry =~ m/^\.\.?$/);
                cxlog("  [$dentry]\n");
                if ($dentry =~ /$pattern/)
                {
                    $dentry="$self->{wmdir}$dir/$dentry";
                    cxlog("Deleting '$dentry'\n");
                    if (!unlink $dentry)
                    {
                        cxerr("unable to delete '$dentry': $!\n");
                        $rc=0;
                    }
                    $self->{update}=1;
                }
                elsif (-d "$self->{wmdir}$dir/$dentry")
                {
                    push @dirs, "$dir/$dentry";
                    $self->{garbage_collect}->{"$dir/$dentry"}=1;
                }
            }
            closedir($dh);
        }
        elsif (-d "$self->{wmdir}$dir")
        {
            cxlog("unable to open the '$self->{wmdir}$dir' directory: $!\n");
            $rc=0;
        }
    }

    return $rc;
}

sub gc_get_folder_status($$)
{
    my ($self, $path)=@_;

    my @actions=keys %{$self->{dtfile}->{actions}};
    if (@actions)
    {
        # If actions is non-empty, then install() was called,
        # and thus tag is set
        cxlog("actions=[", join(":", @actions),"]\n");
        my $mangled="cxmenu-$self->{tag}" . mangle_string("$path/");
        return "in-use" if (grep m%^\Q$mangled\E$%, @actions);
    }

    if (opendir(my $dh, "$self->{wmdir}$path"))
    {
        foreach my $dentry (readdir $dh)
        {
            if ($dentry !~ /^\.\.?$/)
            {
                closedir($dh);
                return "in-use";
            }
        }
        closedir($dh);
    }
    return "empty";
}

sub gc_delete_folder($$$)
{
    my ($self, $path)=@_;

    cxlog("Deleting the '$path' directory\n");
    my $dir="$self->{wmdir}$path";
    if (-d $dir)
    {
        cxlog("Deleting '$dir'\n");
        if (!rmdir $dir)
        {
            cxerr("unable to delete the '$dir' directory: $!\n");
            return 0;
        }
    }
}

sub finalize($)
{
    my ($self)=@_;

    $self->SUPER::finalize();

    if ($self->{modified})
    {
        if ($self->{dtfile}->is_empty())
        {
            my $filename="$self->{destdir}$self->{dtfile}->{filename}";
            cxlog("deleting empty '$filename' file\n");
            # Delete the menu file
            if (-e $filename and !unlink $filename)
            {
                cxerr("unable to delete '$filename': $!\n");
                return 0;
            }
        }
        elsif (!$self->{dtfile}->save())
        {
            cxerr("unable to save '$self->{dtfile}->{filename}'\n");
        }
        $self->{update}=1;
    }
    if ($self->{update} and $self->{scope} ne "managed")
    {
        # Make sure we only run one instance at a time (just to be safe).
        my $lock=CXUtils::cxlock("cde");
        # Update ~/.dt/$LANG/wsmenu.dtwmrc
        cxsystem($self->{dtaction}, "BuildDtwmrcFromWsmenuDir");
        # And cause CDE to reload it
        cxsystem($self->{dtaction}, "RegenerateWorkspaceMenu");
        CXUtils::cxunlock($lock);
    }
    return 1;
}

return 1;