PARTIAL update zig 0.10.0 -> 0.13.0 (Linux only)
This commit is contained in:
		
							parent
							
								
									c29716cc5e
								
							
						
					
					
						commit
						b57611439f
					
				
					 8 changed files with 104 additions and 393 deletions
				
			
		
							
								
								
									
										206
									
								
								GitRepoStep.zig
									
										
									
									
									
								
							
							
						
						
									
										206
									
								
								GitRepoStep.zig
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,206 +0,0 @@
 | 
			
		|||
//! Publish Date: 2021_10_17
 | 
			
		||||
//! This file is hosted at github.com/marler8997/zig-build-repos and is meant to be copied
 | 
			
		||||
//! to projects that use it.
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const GitRepoStep = @This();
 | 
			
		||||
 | 
			
		||||
pub const ShaCheck = enum {
 | 
			
		||||
    none,
 | 
			
		||||
    warn,
 | 
			
		||||
    err,
 | 
			
		||||
 | 
			
		||||
    pub fn reportFail(self: ShaCheck, comptime fmt: []const u8, args: anytype) void {
 | 
			
		||||
        switch (self) {
 | 
			
		||||
            .none => unreachable,
 | 
			
		||||
            .warn => std.log.warn(fmt, args),
 | 
			
		||||
            .err => {
 | 
			
		||||
                std.log.err(fmt, args);
 | 
			
		||||
                std.os.exit(0xff);
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
step: std.build.Step,
 | 
			
		||||
builder: *std.build.Builder,
 | 
			
		||||
url: []const u8,
 | 
			
		||||
name: []const u8,
 | 
			
		||||
branch: ?[]const u8 = null,
 | 
			
		||||
sha: []const u8,
 | 
			
		||||
path: []const u8 = null,
 | 
			
		||||
sha_check: ShaCheck = .warn,
 | 
			
		||||
fetch_enabled: bool,
 | 
			
		||||
 | 
			
		||||
var cached_default_fetch_option: ?bool = null;
 | 
			
		||||
pub fn defaultFetchOption(b: *std.build.Builder) bool {
 | 
			
		||||
    if (cached_default_fetch_option) |_| {} else {
 | 
			
		||||
        cached_default_fetch_option = if (b.option(bool, "fetch", "automatically fetch network resources")) |o| o else false;
 | 
			
		||||
    }
 | 
			
		||||
    return cached_default_fetch_option.?;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn create(b: *std.build.Builder, opt: struct {
 | 
			
		||||
    url: []const u8,
 | 
			
		||||
    branch: ?[]const u8 = null,
 | 
			
		||||
    sha: []const u8,
 | 
			
		||||
    path: ?[]const u8 = null,
 | 
			
		||||
    sha_check: ShaCheck = .warn,
 | 
			
		||||
    fetch_enabled: ?bool = null,
 | 
			
		||||
}) *GitRepoStep {
 | 
			
		||||
    var result = b.allocator.create(GitRepoStep) catch @panic("memory");
 | 
			
		||||
    const name = std.fs.path.basename(opt.url);
 | 
			
		||||
    result.* = GitRepoStep{
 | 
			
		||||
        .step = std.build.Step.init(.custom, "clone a git repository", b.allocator, make),
 | 
			
		||||
        .builder = b,
 | 
			
		||||
        .url = opt.url,
 | 
			
		||||
        .name = name,
 | 
			
		||||
        .branch = opt.branch,
 | 
			
		||||
        .sha = opt.sha,
 | 
			
		||||
        .path = if (opt.path) |p| (b.allocator.dupe(u8, p) catch @panic("memory")) else (std.fs.path.resolve(b.allocator, &[_][]const u8{
 | 
			
		||||
            b.build_root,
 | 
			
		||||
            "libs",
 | 
			
		||||
            name,
 | 
			
		||||
        })) catch @panic("memory"),
 | 
			
		||||
        .sha_check = opt.sha_check,
 | 
			
		||||
        .fetch_enabled = if (opt.fetch_enabled) |fe| fe else defaultFetchOption(b),
 | 
			
		||||
    };
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: this should be included in std.build, it helps find bugs in build files
 | 
			
		||||
fn hasDependency(step: *const std.build.Step, dep_candidate: *const std.build.Step) bool {
 | 
			
		||||
    for (step.dependencies.items) |dep| {
 | 
			
		||||
        // TODO: should probably use step.loop_flag to prevent infinite recursion
 | 
			
		||||
        //       when a circular reference is encountered, or maybe keep track of
 | 
			
		||||
        //       the steps encounterd with a hash set
 | 
			
		||||
        if (dep == dep_candidate or hasDependency(dep, dep_candidate))
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn make(step: *std.build.Step) !void {
 | 
			
		||||
    const self = @fieldParentPtr(GitRepoStep, "step", step);
 | 
			
		||||
 | 
			
		||||
    std.fs.accessAbsolute(self.path, std.fs.File.OpenFlags{ .read = true }) catch {
 | 
			
		||||
        const branch_args = if (self.branch) |b| &[2][]const u8{ " -b ", b } else &[2][]const u8{ "", "" };
 | 
			
		||||
        if (!self.fetch_enabled) {
 | 
			
		||||
            std.debug.print("Error: git repository '{s}' does not exist\n", .{self.path});
 | 
			
		||||
            std.debug.print("       Use -Dfetch to download it automatically, or run the following to clone it:\n", .{});
 | 
			
		||||
            std.debug.print("       git clone {s}{s}{s} {s} && git -C {3s} checkout {s} -b for_ziget\n", .{ self.url, branch_args[0], branch_args[1], self.path, self.sha });
 | 
			
		||||
            std.os.exit(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            var args = std.ArrayList([]const u8).init(self.builder.allocator);
 | 
			
		||||
            defer args.deinit();
 | 
			
		||||
            try args.append("git");
 | 
			
		||||
            try args.append("clone");
 | 
			
		||||
            try args.append("--recurse-submodules");
 | 
			
		||||
            try args.append(self.url);
 | 
			
		||||
            // TODO: clone it to a temporary location in case of failure
 | 
			
		||||
            //       also, remove that temporary location before running
 | 
			
		||||
            try args.append(self.path);
 | 
			
		||||
            if (self.branch) |branch| {
 | 
			
		||||
                try args.append("-b");
 | 
			
		||||
                try args.append(branch);
 | 
			
		||||
            }
 | 
			
		||||
            try run(self.builder, args.items);
 | 
			
		||||
        }
 | 
			
		||||
        try run(self.builder, &[_][]const u8{
 | 
			
		||||
            "git",
 | 
			
		||||
            "-C",
 | 
			
		||||
            self.path,
 | 
			
		||||
            "checkout",
 | 
			
		||||
            self.sha,
 | 
			
		||||
            "-b",
 | 
			
		||||
            "fordep",
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    try self.checkSha();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn checkSha(self: GitRepoStep) !void {
 | 
			
		||||
    if (self.sha_check == .none)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    const result: union(enum) { failed: anyerror, output: []const u8 } = blk: {
 | 
			
		||||
        const result = std.ChildProcess.exec(.{
 | 
			
		||||
            .allocator = self.builder.allocator,
 | 
			
		||||
            .argv = &[_][]const u8{
 | 
			
		||||
                "git",
 | 
			
		||||
                "-C",
 | 
			
		||||
                self.path,
 | 
			
		||||
                "rev-parse",
 | 
			
		||||
                "HEAD",
 | 
			
		||||
            },
 | 
			
		||||
            .cwd = self.builder.build_root,
 | 
			
		||||
            .env_map = self.builder.env_map,
 | 
			
		||||
        }) catch |e| break :blk .{ .failed = e };
 | 
			
		||||
        try std.io.getStdErr().writer().writeAll(result.stderr);
 | 
			
		||||
        switch (result.term) {
 | 
			
		||||
            .Exited => |code| {
 | 
			
		||||
                if (code == 0) break :blk .{ .output = result.stdout };
 | 
			
		||||
                break :blk .{ .failed = error.GitProcessNonZeroExit };
 | 
			
		||||
            },
 | 
			
		||||
            .Signal => break :blk .{ .failed = error.GitProcessFailedWithSignal },
 | 
			
		||||
            .Stopped => break :blk .{ .failed = error.GitProcessWasStopped },
 | 
			
		||||
            .Unknown => break :blk .{ .failed = error.GitProcessFailed },
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    switch (result) {
 | 
			
		||||
        .failed => |err| {
 | 
			
		||||
            return self.sha_check.reportFail("failed to retreive sha for repository '{s}': {s}", .{ self.name, @errorName(err) });
 | 
			
		||||
        },
 | 
			
		||||
        .output => |output| {
 | 
			
		||||
            if (!std.mem.eql(u8, std.mem.trimRight(u8, output, "\n\r"), self.sha)) {
 | 
			
		||||
                return self.sha_check.reportFail("repository '{s}' sha does not match\nexpected: {s}\nactual  : {s}\n", .{ self.name, self.sha, output });
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn run(builder: *std.build.Builder, argv: []const []const u8) !void {
 | 
			
		||||
    {
 | 
			
		||||
        var msg = std.ArrayList(u8).init(builder.allocator);
 | 
			
		||||
        defer msg.deinit();
 | 
			
		||||
        const writer = msg.writer();
 | 
			
		||||
        var prefix: []const u8 = "";
 | 
			
		||||
        for (argv) |arg| {
 | 
			
		||||
            try writer.print("{s}\"{s}\"", .{ prefix, arg });
 | 
			
		||||
            prefix = " ";
 | 
			
		||||
        }
 | 
			
		||||
        std.log.info("[RUN] {s}", .{msg.items});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const child = try std.ChildProcess.init(argv, builder.allocator);
 | 
			
		||||
    defer child.deinit();
 | 
			
		||||
 | 
			
		||||
    child.stdin_behavior = .Ignore;
 | 
			
		||||
    child.stdout_behavior = .Inherit;
 | 
			
		||||
    child.stderr_behavior = .Inherit;
 | 
			
		||||
    child.cwd = builder.build_root;
 | 
			
		||||
    child.env_map = builder.env_map;
 | 
			
		||||
 | 
			
		||||
    try child.spawn();
 | 
			
		||||
    const result = try child.wait();
 | 
			
		||||
    switch (result) {
 | 
			
		||||
        .Exited => |code| if (code != 0) {
 | 
			
		||||
            std.log.err("git clone failed with exit code {}", .{code});
 | 
			
		||||
            std.os.exit(0xff);
 | 
			
		||||
        },
 | 
			
		||||
        else => {
 | 
			
		||||
            std.log.err("git clone failed with: {}", .{result});
 | 
			
		||||
            std.os.exit(0xff);
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get's the repository path and also verifies that the step requesting the path
 | 
			
		||||
// is dependent on this step.
 | 
			
		||||
pub fn getPath(self: *const GitRepoStep, who_wants_to_know: *const std.build.Step) []const u8 {
 | 
			
		||||
    if (!hasDependency(who_wants_to_know, &self.step))
 | 
			
		||||
        @panic("a step called GitRepoStep.getPath but has not added it as a dependency");
 | 
			
		||||
    return self.path;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										136
									
								
								build.zig
									
										
									
									
									
								
							
							
						
						
									
										136
									
								
								build.zig
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,12 +1,6 @@
 | 
			
		|||
const std = @import("std");
 | 
			
		||||
const GitRepoStep = @import("GitRepoStep.zig");
 | 
			
		||||
 | 
			
		||||
pub fn build(b: *std.build.Builder) void {
 | 
			
		||||
    const zfetch_repo = GitRepoStep.create(b, .{
 | 
			
		||||
        .url = "https://github.com/truemedian/zfetch",
 | 
			
		||||
        // .branch = "0.1.10", // branch also takes tags. Tag 0.1.10 isn't quite new enough
 | 
			
		||||
        .sha = "271cab5da4d12c8f08e67aa0cd5268da100e52f1",
 | 
			
		||||
    });
 | 
			
		||||
pub fn build(b: *std.Build) void {
 | 
			
		||||
    // Standard target options allows the person running `zig build` to choose
 | 
			
		||||
    // what target to build for. Here we do not override the defaults, which
 | 
			
		||||
    // means any target is allowed, and the default is native. Other options
 | 
			
		||||
| 
						 | 
				
			
			@ -15,12 +9,12 @@ pub fn build(b: *std.build.Builder) void {
 | 
			
		|||
 | 
			
		||||
    // Standard release options allow the person running `zig build` to select
 | 
			
		||||
    // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
 | 
			
		||||
    const mode = b.standardReleaseOptions();
 | 
			
		||||
    const optimize = b.standardOptimizeOption(.{});
 | 
			
		||||
 | 
			
		||||
    const uploadexe = switch (target.getOs().tag) {
 | 
			
		||||
        .linux => b.addExecutable("clipboard-upload", "src/main-linux.zig"),
 | 
			
		||||
        .windows => b.addExecutable("clipboard-upload", "src/main-windows.zig"),
 | 
			
		||||
        else => std.os.exit(1),
 | 
			
		||||
    const uploadexe = switch (target.result.os.tag) {
 | 
			
		||||
        .linux => b.addExecutable(.{ .name = "clipboard-upload", .root_source_file = b.path("src/main-linux.zig"), .target = target }),
 | 
			
		||||
        .windows => b.addExecutable(.{ .name = "clipboard-upload", .root_source_file = b.path("src/main-windows.zig"), .target = target }),
 | 
			
		||||
        else => std.process.exit(1),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const path = if (b.option(bool, "curl", "use external curl command") orelse false)
 | 
			
		||||
| 
						 | 
				
			
			@ -30,19 +24,22 @@ pub fn build(b: *std.build.Builder) void {
 | 
			
		|||
 | 
			
		||||
    const enc_path = blk: {
 | 
			
		||||
        if (b.option(bool, "seperate-encryption", "use external encryption command") orelse false) {
 | 
			
		||||
            const encryptionexe = b.addExecutable("encrypt", "src/encrypt.zig");
 | 
			
		||||
            encryptionexe.setTarget(target);
 | 
			
		||||
            encryptionexe.setBuildMode(mode);
 | 
			
		||||
            encryptionexe.install();
 | 
			
		||||
            const encryptionexe = b.addExecutable(.{
 | 
			
		||||
                .name = "encrypt",
 | 
			
		||||
                .root_source_file = b.path("src/encrypt.zig"),
 | 
			
		||||
                .target = target,
 | 
			
		||||
                .optimize = optimize,
 | 
			
		||||
            });
 | 
			
		||||
            b.getInstallStep().dependOn(&b.addInstallArtifact(encryptionexe, .{}).step);
 | 
			
		||||
            break :blk "config/external_encryption.zig";
 | 
			
		||||
        } else {
 | 
			
		||||
            break :blk "config/sane_encryption.zig";
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    configureExe(uploadexe, b, target, mode, zfetch_repo, path, enc_path);
 | 
			
		||||
    configureExe(uploadexe, b, target, optimize, path, enc_path);
 | 
			
		||||
 | 
			
		||||
    const run_cmd = uploadexe.run();
 | 
			
		||||
    const run_cmd = b.addRunArtifact(uploadexe);
 | 
			
		||||
    run_cmd.step.dependOn(b.getInstallStep());
 | 
			
		||||
    if (b.args) |args| {
 | 
			
		||||
        run_cmd.addArgs(args);
 | 
			
		||||
| 
						 | 
				
			
			@ -51,11 +48,11 @@ pub fn build(b: *std.build.Builder) void {
 | 
			
		|||
    const run_step = b.step("run", "Run the app (uplaods clipboard contents)");
 | 
			
		||||
    run_step.dependOn(&run_cmd.step);
 | 
			
		||||
 | 
			
		||||
    const downloadexe = b.addExecutable("clipboard-download", "src/download.zig");
 | 
			
		||||
    const downloadexe = b.addExecutable(.{ .name = "clipboard-download", .root_source_file = b.path("src/download.zig"), .target = target });
 | 
			
		||||
 | 
			
		||||
    configureExe(downloadexe, b, target, mode, zfetch_repo, path, enc_path);
 | 
			
		||||
    configureExe(downloadexe, b, target, optimize, path, enc_path);
 | 
			
		||||
 | 
			
		||||
    const run_download_cmd = downloadexe.run();
 | 
			
		||||
    const run_download_cmd = b.addRunArtifact(downloadexe);
 | 
			
		||||
    run_download_cmd.step.dependOn(b.getInstallStep());
 | 
			
		||||
    if (b.args) |args| {
 | 
			
		||||
        run_download_cmd.addArgs(args);
 | 
			
		||||
| 
						 | 
				
			
			@ -65,10 +62,9 @@ pub fn build(b: *std.build.Builder) void {
 | 
			
		|||
    run_download_step.dependOn(&run_download_cmd.step);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn configureExe(exe: *std.build.LibExeObjStep, b: *std.build.Builder, target: std.zig.CrossTarget, mode: std.builtin.Mode, zfetch_repo: anytype, config_path: []const u8, enc_config_path: []const u8) void {
 | 
			
		||||
    exe.setTarget(target);
 | 
			
		||||
    exe.setBuildMode(mode);
 | 
			
		||||
    if (target.getOs().tag == .linux) {
 | 
			
		||||
fn configureExe(exe: *std.Build.Step.Compile, b: *std.Build, target: std.Build.ResolvedTarget, mode: std.builtin.OptimizeMode, config_path: []const u8, enc_config_path: []const u8) void {
 | 
			
		||||
    exe.root_module.optimize = mode;
 | 
			
		||||
    if (target.result.os.tag == .linux) {
 | 
			
		||||
        exe.linkLibC();
 | 
			
		||||
        // LibX11 1.7.2: https://gitlab.freedesktop.org/xorg/lib/libx11/-/archive/libX11-1.7.2/libx11-libX11-1.7.2.tar.gz
 | 
			
		||||
        // LibXfixes 5.0.3: https://gitlab.freedesktop.org/xorg/lib/libxfixes/-/archive/libXfixes-5.0.3/libxfixes-libXfixes-5.0.3.tar.gz
 | 
			
		||||
| 
						 | 
				
			
			@ -76,93 +72,39 @@ fn configureExe(exe: *std.build.LibExeObjStep, b: *std.build.Builder, target: st
 | 
			
		|||
        // We can download the above by taking each url and processing in a
 | 
			
		||||
        // command e.g.:
 | 
			
		||||
        // curl <url> | tar xz --wildcards '*.h'
 | 
			
		||||
        exe.addIncludeDir("libx11-libX11-1.7.2/include");
 | 
			
		||||
        exe.addIncludeDir("libxfixes-libXfixes-5.0.3/include");
 | 
			
		||||
        exe.addIncludeDir("xorgproto-xorgproto-2021.5/include");
 | 
			
		||||
        exe.addIncludePath(b.path("libx11-libX11-1.7.2/include"));
 | 
			
		||||
        exe.addIncludePath(b.path("libxfixes-libXfixes-5.0.3/include"));
 | 
			
		||||
        exe.addIncludePath(b.path("xorgproto-xorgproto-2021.5/include"));
 | 
			
		||||
 | 
			
		||||
        // More than a little messy. We're grabbing libX11 and libXfixes from
 | 
			
		||||
        // the host, while using downloaded headers. This assumes debian
 | 
			
		||||
        // bullseye host, and also means you can't cross-compile from Windows.
 | 
			
		||||
        // TODO: Make this better
 | 
			
		||||
        // const dependent_objects = .{
 | 
			
		||||
        //     "/usr/lib/x86_64-linux-gnu/libX11.so.6",
 | 
			
		||||
        //     "/usr/lib/x86_64-linux-gnu/libXfixes.so.3",
 | 
			
		||||
        // };
 | 
			
		||||
        const dependent_objects = .{
 | 
			
		||||
            "/usr/lib/x86_64-linux-gnu/libX11.so.6",
 | 
			
		||||
            "/usr/lib/x86_64-linux-gnu/libXfixes.so.3",
 | 
			
		||||
            "/nix/store/wd7b3f9sqgs0flgicx213iiyzjb4jxqm-libXfixes-6.0.1/lib/libXfixes.so.3",
 | 
			
		||||
        };
 | 
			
		||||
        inline for (dependent_objects) |obj|
 | 
			
		||||
            exe.addObjectFile(obj);
 | 
			
		||||
            exe.addObjectFile(.{ .cwd_relative = obj });
 | 
			
		||||
        // exe.addObjectFile(b.path(obj));
 | 
			
		||||
    }
 | 
			
		||||
    if (target.getOs().tag == .windows) {
 | 
			
		||||
    if (target.result.os.tag == .windows) {
 | 
			
		||||
        // woah...we don't actually need libc!
 | 
			
		||||
        exe.linkSystemLibrary("user32");
 | 
			
		||||
        exe.linkSystemLibrary("kernel32");
 | 
			
		||||
        exe.linkSystemLibrary("shell32");
 | 
			
		||||
    }
 | 
			
		||||
    const copy_deps = std.build.RunStep.create(b, "copy zfetch deps");
 | 
			
		||||
    copy_deps.addArgs(&[_][]const u8{
 | 
			
		||||
        "cp",
 | 
			
		||||
        "zfetch_deps.zig",
 | 
			
		||||
        "libs/zfetch/deps.zig",
 | 
			
		||||
    });
 | 
			
		||||
    copy_deps.step.dependOn(&zfetch_repo.step);
 | 
			
		||||
 | 
			
		||||
    // exe.step.dependOn(&zfetch_repo.step);
 | 
			
		||||
    exe.step.dependOn(©_deps.step);
 | 
			
		||||
    exe.root_module.addImport("config", b.createModule(.{
 | 
			
		||||
        .root_source_file = b.path(config_path),
 | 
			
		||||
    }));
 | 
			
		||||
    exe.root_module.addImport("encryptionconfig", b.createModule(.{
 | 
			
		||||
        .root_source_file = b.path(enc_config_path),
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    // This import won't work unless we're already cloned. The way around
 | 
			
		||||
    // this is to have a multi-stage build process, but that's a lot of work.
 | 
			
		||||
    // Instead, I've copied the addPackage and tweaked it for the build prefix
 | 
			
		||||
    // so we'll have to keep that in sync with upstream
 | 
			
		||||
    // const zfetch = @import("libs/zfetch/build.zig");
 | 
			
		||||
    const zpkg = getZfetchPackage(b, "libs/zfetch") catch unreachable;
 | 
			
		||||
    exe.addPackage(zpkg);
 | 
			
		||||
    exe.addPackage(.{
 | 
			
		||||
        .name = "iguanaTLS",
 | 
			
		||||
        .path = .{ .path = "libs/zfetch/libs/iguanaTLS/src/main.zig" },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    exe.addPackage(.{
 | 
			
		||||
        .name = "config",
 | 
			
		||||
        .path = .{ .path = config_path },
 | 
			
		||||
    });
 | 
			
		||||
    exe.addPackage(.{
 | 
			
		||||
        .name = "encryptionconfig",
 | 
			
		||||
        .path = .{ .path = enc_config_path },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    exe.install();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn getDependency(comptime lib_prefix: []const u8, comptime name: []const u8, comptime root: []const u8) !std.build.Pkg {
 | 
			
		||||
    const path = lib_prefix ++ "/libs/" ++ name ++ "/" ++ root;
 | 
			
		||||
 | 
			
		||||
    // We don't actually care if the dependency has been checked out, as
 | 
			
		||||
    // GitRepoStep will handle that for us
 | 
			
		||||
    // Make sure that the dependency has been checked out.
 | 
			
		||||
    // std.fs.cwd().access(path, .{}) catch |err| switch (err) {
 | 
			
		||||
    //     error.FileNotFound => {
 | 
			
		||||
    //         std.log.err("zfetch: dependency '{s}' not checked out", .{name});
 | 
			
		||||
    //
 | 
			
		||||
    //         return err;
 | 
			
		||||
    //     },
 | 
			
		||||
    //     else => return err,
 | 
			
		||||
    // };
 | 
			
		||||
 | 
			
		||||
    return std.build.Pkg{
 | 
			
		||||
        .name = name,
 | 
			
		||||
        .path = .{ .path = path },
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
pub fn getZfetchPackage(b: *std.build.Builder, comptime lib_prefix: []const u8) !std.build.Pkg {
 | 
			
		||||
    var dependencies = b.allocator.alloc(std.build.Pkg, 4) catch unreachable;
 | 
			
		||||
 | 
			
		||||
    dependencies[0] = try getDependency(lib_prefix, "iguanaTLS", "src/main.zig");
 | 
			
		||||
    dependencies[1] = try getDependency(lib_prefix, "network", "network.zig");
 | 
			
		||||
    dependencies[2] = try getDependency(lib_prefix, "uri", "uri.zig");
 | 
			
		||||
    dependencies[3] = try getDependency(lib_prefix, "hzzp", "src/main.zig");
 | 
			
		||||
 | 
			
		||||
    return std.build.Pkg{
 | 
			
		||||
        .name = "zfetch",
 | 
			
		||||
        .path = .{ .path = lib_prefix ++ "/src/main.zig" },
 | 
			
		||||
        .dependencies = dependencies,
 | 
			
		||||
    };
 | 
			
		||||
    b.getInstallStep().dependOn(&b.addInstallArtifact(exe, .{}).step);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
const builtin = @import("builtin");
 | 
			
		||||
const std = @import("std");
 | 
			
		||||
const zfetch = @import("zfetch");
 | 
			
		||||
const crypt = @import("crypt.zig");
 | 
			
		||||
const config = @import("config");
 | 
			
		||||
const encryptionconfig = @import("encryptionconfig");
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +12,7 @@ const encryptionconfig = @import("encryptionconfig");
 | 
			
		|||
// iguanaTLS to support tls 1.3
 | 
			
		||||
// iguanaTLS to support something else, like ECDHE-ECDSA-CHACHA20-POLY1305
 | 
			
		||||
// In the meantime, I've allowed use of http, since we're encrypting anyway
 | 
			
		||||
const clipboard_url = "http://clippy.lerch.org/work2";
 | 
			
		||||
const clipboard_url = "https://clippy.lerch.org/work2";
 | 
			
		||||
// const clipboard_url = "https://httpbin.org/post";
 | 
			
		||||
 | 
			
		||||
const Self = @This();
 | 
			
		||||
| 
						 | 
				
			
			@ -59,9 +58,8 @@ pub fn clipboardChanged(self: *Self, contents: []const u8) !void {
 | 
			
		|||
    defer aa.free(clip_contents);
 | 
			
		||||
 | 
			
		||||
    // Ugh - it's the encryption that Crowdstrike doesn't like.. :(
 | 
			
		||||
    var buf: []u8 = try aa.alloc(u8, contents.len);
 | 
			
		||||
    const buf: []u8 = try aa.dupe(u8, contents);
 | 
			
		||||
    defer aa.free(buf);
 | 
			
		||||
    std.mem.copy(u8, buf, contents);
 | 
			
		||||
    const encrypted = encrypt(aa, self.key.*, buf) catch |e| {
 | 
			
		||||
        std.log.err("Could not encrypt clipboard contents: {}", .{e});
 | 
			
		||||
        if (@errorReturnTrace()) |trace| {
 | 
			
		||||
| 
						 | 
				
			
			@ -127,19 +125,20 @@ fn get(allocator: std.mem.Allocator) ![]const u8 {
 | 
			
		|||
    //     @embedFile("/etc/ssl/certs/ca-certificates.crt"),
 | 
			
		||||
    // ).reader();
 | 
			
		||||
    // const trust = try tls.x509.CertificateChain.from_pem(allocator, cert_reader);
 | 
			
		||||
    try zfetch.init();
 | 
			
		||||
    defer zfetch.deinit();
 | 
			
		||||
 | 
			
		||||
    var headers = zfetch.Headers.init(allocator);
 | 
			
		||||
    defer headers.deinit();
 | 
			
		||||
 | 
			
		||||
    // try headers.appendValue("Accept", "application/json");
 | 
			
		||||
    // try headers.appendValue("Content-Type", "text/plain");
 | 
			
		||||
 | 
			
		||||
    var req = try zfetch.Request.init(allocator, clipboard_url, null);
 | 
			
		||||
    defer req.deinit();
 | 
			
		||||
    var data = std.ArrayList(u8).init(allocator);
 | 
			
		||||
    defer data.deinit();
 | 
			
		||||
    var client = std.http.Client{ .allocator = allocator };
 | 
			
		||||
    defer client.deinit();
 | 
			
		||||
 | 
			
		||||
    try req.do(.GET, headers, null);
 | 
			
		||||
    const res = try client.fetch(.{
 | 
			
		||||
        .location = .{ .url = clipboard_url },
 | 
			
		||||
        .response_storage = .{ .dynamic = &data },
 | 
			
		||||
    });
 | 
			
		||||
    _ = res; // TODO: Check res.status
 | 
			
		||||
 | 
			
		||||
    // Printf debugging
 | 
			
		||||
    // const stdout = std.io.getStdOut().writer();
 | 
			
		||||
| 
						 | 
				
			
			@ -150,18 +149,6 @@ fn get(allocator: std.mem.Allocator) ![]const u8 {
 | 
			
		|||
    // }
 | 
			
		||||
    // try stdout.print("body:\n", .{});
 | 
			
		||||
    //
 | 
			
		||||
    const reader = req.reader();
 | 
			
		||||
 | 
			
		||||
    var data = std.ArrayList(u8).init(allocator);
 | 
			
		||||
    defer data.deinit();
 | 
			
		||||
    const data_writer = data.writer();
 | 
			
		||||
    var buf: [1024]u8 = undefined;
 | 
			
		||||
    while (true) {
 | 
			
		||||
        const read = try reader.read(&buf);
 | 
			
		||||
        if (read == 0) break;
 | 
			
		||||
 | 
			
		||||
        try data_writer.writeAll(buf[0..read]);
 | 
			
		||||
    }
 | 
			
		||||
    return data.toOwnedSlice();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -270,42 +257,20 @@ fn put(allocator: std.mem.Allocator, data: []const u8) !void {
 | 
			
		|||
    //     @embedFile("/etc/ssl/certs/ca-certificates.crt"),
 | 
			
		||||
    // ).reader();
 | 
			
		||||
    // const trust = try tls.x509.CertificateChain.from_pem(allocator, cert_reader);
 | 
			
		||||
    try zfetch.init();
 | 
			
		||||
    defer zfetch.deinit();
 | 
			
		||||
    var client = std.http.Client{ .allocator = allocator };
 | 
			
		||||
    defer client.deinit();
 | 
			
		||||
 | 
			
		||||
    var headers = zfetch.Headers.init(allocator);
 | 
			
		||||
    defer headers.deinit();
 | 
			
		||||
    const res = try client.fetch(.{
 | 
			
		||||
        .location = .{ .url = clipboard_url },
 | 
			
		||||
        .method = .PUT,
 | 
			
		||||
        .payload = data,
 | 
			
		||||
    });
 | 
			
		||||
    _ = res; // TODO: check status
 | 
			
		||||
 | 
			
		||||
    // try headers.appendValue("Accept", "application/json");
 | 
			
		||||
    // try headers.appendValue("Content-Type", "text/plain");
 | 
			
		||||
 | 
			
		||||
    var req = try zfetch.Request.init(allocator, clipboard_url, null);
 | 
			
		||||
    defer req.deinit();
 | 
			
		||||
 | 
			
		||||
    try req.do(.PUT, headers, data);
 | 
			
		||||
 | 
			
		||||
    // Printf debugging
 | 
			
		||||
    // const stdout = std.io.getStdOut().writer();
 | 
			
		||||
    // try stdout.print("status: {d} {s}\n", .{ req.status.code, req.status.reason });
 | 
			
		||||
    // try stdout.print("headers:\n", .{});
 | 
			
		||||
    // for (req.headers.list.items) |header| {
 | 
			
		||||
    //     try stdout.print("  {s}: {s}\n", .{ header.name, header.value });
 | 
			
		||||
    // }
 | 
			
		||||
    // try stdout.print("body:\n", .{});
 | 
			
		||||
    //
 | 
			
		||||
    // const reader = req.reader();
 | 
			
		||||
    //
 | 
			
		||||
    // var buf: [1024]u8 = undefined;
 | 
			
		||||
    // while (true) {
 | 
			
		||||
    //     const read = try reader.read(&buf);
 | 
			
		||||
    //     if (read == 0) break;
 | 
			
		||||
    //
 | 
			
		||||
    //     try stdout.writeAll(buf[0..read]);
 | 
			
		||||
    // }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
test "full integration" {
 | 
			
		||||
    var allocator = std.testing.allocator;
 | 
			
		||||
    const allocator = std.testing.allocator;
 | 
			
		||||
    var watcher = init(allocator);
 | 
			
		||||
    defer watcher.deinit();
 | 
			
		||||
    try watcher.clipboardChanged("hello world");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,7 @@ pub fn encryptWithKey(allocator: std.mem.Allocator, key: [key_size]u8, data: []u
 | 
			
		|||
    var encrypted = try std.ArrayList(u8).initCapacity(allocator, block_size * (total_blocks + 1));
 | 
			
		||||
    defer encrypted.deinit();
 | 
			
		||||
    while (current_block < total_blocks) {
 | 
			
		||||
        in = @ptrCast(*[block_size]u8, data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]);
 | 
			
		||||
        in = @ptrCast(data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]);
 | 
			
		||||
        ctx.encrypt(out[0..], in.*[0..]);
 | 
			
		||||
        encrypted.appendSliceAssumeCapacity(out[0..]);
 | 
			
		||||
        current_block += 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ pub fn encryptWithKey(allocator: std.mem.Allocator, key: [key_size]u8, data: []u
 | 
			
		|||
        // We can't just ptrcast into data as we are likely to run over the end
 | 
			
		||||
        // of the data memory. We'll declare a new input buffer
 | 
			
		||||
        var in_last: [block_size]u8 = undefined;
 | 
			
		||||
        const padding: u8 = @intCast(u8, block_size - (data.len % block_size));
 | 
			
		||||
        const padding: u8 = @intCast(block_size - (data.len % block_size));
 | 
			
		||||
        var inx: u8 = 0;
 | 
			
		||||
        for (data[(total_blocks * block_size)..]) |b| {
 | 
			
		||||
            in_last[inx] = b;
 | 
			
		||||
| 
						 | 
				
			
			@ -99,14 +99,14 @@ pub fn decryptWithKey(allocator: std.mem.Allocator, key: [key_size]u8, data: []c
 | 
			
		|||
    var decrypted = try std.ArrayList(u8).initCapacity(allocator, block_size * (total_blocks - 1));
 | 
			
		||||
    defer decrypted.deinit();
 | 
			
		||||
    while (current_block < total_blocks - 1) {
 | 
			
		||||
        in = @ptrCast(*const [block_size]u8, data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]);
 | 
			
		||||
        in = @ptrCast(data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]);
 | 
			
		||||
        ctx.decrypt(out[0..], in.*[0..]);
 | 
			
		||||
        decrypted.appendSliceAssumeCapacity(out[0..]);
 | 
			
		||||
        current_block += 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // deal with final block, PKCS#7 padding
 | 
			
		||||
    in = @ptrCast(*const [block_size]u8, data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]);
 | 
			
		||||
    in = @ptrCast(data[(current_block * block_size)..(((current_block + 1) * block_size) - 1)]);
 | 
			
		||||
    ctx.decrypt(out[0..], in.*[0..]);
 | 
			
		||||
    // Assertion was triggering when data was plain text
 | 
			
		||||
    if (out[block_size - 1] > block_size) {
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +131,7 @@ test "correct size, even block" {
 | 
			
		|||
    const str = "0123456789ABCDEF";
 | 
			
		||||
    var allocator = std.testing.allocator;
 | 
			
		||||
    var buf: [str.len]u8 = undefined;
 | 
			
		||||
    var data = try std.fmt.bufPrint(&buf, str, .{});
 | 
			
		||||
    const data = try std.fmt.bufPrint(&buf, str, .{});
 | 
			
		||||
    const encrypted = try encryptWithKey(allocator, test_key, data);
 | 
			
		||||
    defer allocator.free(encrypted);
 | 
			
		||||
    const size: usize = 32;
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +142,7 @@ test "round trip, even block" {
 | 
			
		|||
    const str = "0123456789ABCDEF";
 | 
			
		||||
    var allocator = std.testing.allocator;
 | 
			
		||||
    var buf: [str.len]u8 = undefined;
 | 
			
		||||
    var data = try std.fmt.bufPrint(&buf, str, .{});
 | 
			
		||||
    const data = try std.fmt.bufPrint(&buf, str, .{});
 | 
			
		||||
    const encrypted = try encryptWithKey(allocator, test_key, data);
 | 
			
		||||
    defer allocator.free(encrypted);
 | 
			
		||||
    const decrypted = try decryptWithKey(allocator, test_key, encrypted);
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +155,7 @@ test "round trip, uneven block" {
 | 
			
		|||
    const str = "0123456789ABCDEFG";
 | 
			
		||||
    var allocator = std.testing.allocator;
 | 
			
		||||
    var buf: [str.len]u8 = undefined;
 | 
			
		||||
    var data = try std.fmt.bufPrint(&buf, str, .{});
 | 
			
		||||
    const data = try std.fmt.bufPrint(&buf, str, .{});
 | 
			
		||||
    const encrypted = try encryptWithKey(allocator, test_key, data);
 | 
			
		||||
    defer allocator.free(encrypted);
 | 
			
		||||
    const decrypted = try decryptWithKey(allocator, test_key, encrypted);
 | 
			
		||||
| 
						 | 
				
			
			@ -167,8 +167,8 @@ test "round trip, uneven block, using password" {
 | 
			
		|||
    const str = "0123456789ABCDEFG";
 | 
			
		||||
    var allocator = std.testing.allocator;
 | 
			
		||||
    var buf: [str.len]u8 = undefined;
 | 
			
		||||
    var data = try std.fmt.bufPrint(&buf, str, .{});
 | 
			
		||||
    var key = try keyFromPassword(allocator, "foo", "");
 | 
			
		||||
    const data = try std.fmt.bufPrint(&buf, str, .{});
 | 
			
		||||
    const key = try keyFromPassword(allocator, "foo", "");
 | 
			
		||||
    defer allocator.free(key);
 | 
			
		||||
    const encrypted = try encryptWithKey(allocator, key.*, data);
 | 
			
		||||
    defer allocator.free(encrypted);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,11 +42,9 @@ pub fn main() !u8 {
 | 
			
		|||
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
 | 
			
		||||
    defer _ = gpa.deinit();
 | 
			
		||||
    const allocator = gpa.allocator();
 | 
			
		||||
    var args = std.process.args();
 | 
			
		||||
    var args = try std.process.argsWithAllocator(allocator);
 | 
			
		||||
    defer args.deinit();
 | 
			
		||||
    while (args.next(allocator)) |arg_or_err| {
 | 
			
		||||
        const arg = try arg_or_err;
 | 
			
		||||
        defer allocator.free(arg);
 | 
			
		||||
    while (args.next()) |arg| {
 | 
			
		||||
        if (std.mem.eql(u8, arg, "-w")) {
 | 
			
		||||
            watch = true;
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +99,16 @@ fn addToClipboard(allocator: std.mem.Allocator, data: []const u8) !void {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn execLinux(allocator: std.mem.Allocator, data: []const u8) !std.ChildProcess.ExecResult {
 | 
			
		||||
const Term = struct {
 | 
			
		||||
    allocator: std.mem.Allocator,
 | 
			
		||||
    stderr: []const u8,
 | 
			
		||||
    term: std.process.Child.Term,
 | 
			
		||||
 | 
			
		||||
    pub fn deinit(self: *Term) void {
 | 
			
		||||
        self.allocator.free(self.stderr);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
fn execLinux(allocator: std.mem.Allocator, data: []const u8) !Term {
 | 
			
		||||
    // we need to do this (maybe) because there is no real way to close stdin cleanly, which is what will
 | 
			
		||||
    // kill xclip.
 | 
			
		||||
    //
 | 
			
		||||
| 
						 | 
				
			
			@ -114,15 +121,21 @@ fn execLinux(allocator: std.mem.Allocator, data: []const u8) !std.ChildProcess.E
 | 
			
		|||
    defer allocator.free(xclip_cmd);
 | 
			
		||||
    std.log.debug("cmd: {s}", .{xclip_cmd});
 | 
			
		||||
 | 
			
		||||
    return std.ChildProcess.exec(.{
 | 
			
		||||
        .allocator = allocator,
 | 
			
		||||
        .argv = &[_][]const u8{
 | 
			
		||||
    var child = std.process.Child.init(
 | 
			
		||||
        &[_][]const u8{
 | 
			
		||||
            "/usr/bin/env",
 | 
			
		||||
            "sh",
 | 
			
		||||
            "-c",
 | 
			
		||||
            xclip_cmd,
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
        allocator,
 | 
			
		||||
    );
 | 
			
		||||
    const term = try std.process.Child.spawnAndWait(&child);
 | 
			
		||||
    return .{
 | 
			
		||||
        .term = term,
 | 
			
		||||
        .allocator = allocator,
 | 
			
		||||
        .stderr = if (child.stderr) |e| try e.readToEndAlloc(allocator, 10 * 1024 * 1024) else try allocator.dupe(u8, ""),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn execWindows(allocator: std.mem.Allocator, data: []const u8) !std.ChildProcess.ExecResult {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,11 +12,9 @@ pub fn main() !u8 {
 | 
			
		|||
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
 | 
			
		||||
    defer _ = gpa.deinit();
 | 
			
		||||
    const allocator = gpa.allocator();
 | 
			
		||||
    var args = std.process.args();
 | 
			
		||||
    var args = try std.process.argsWithAllocator(allocator);
 | 
			
		||||
    defer args.deinit();
 | 
			
		||||
    while (args.next(allocator)) |arg_or_err| {
 | 
			
		||||
        const arg = try arg_or_err;
 | 
			
		||||
        defer allocator.free(arg);
 | 
			
		||||
    while (args.next()) |arg| {
 | 
			
		||||
        if (std.mem.eql(u8, arg, "-w")) {
 | 
			
		||||
            watch = true;
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -29,15 +27,15 @@ pub fn main() !u8 {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
fn clipboardAction(allocator: std.mem.Allocator, watch: bool, clip: *Clipboard) !void {
 | 
			
		||||
    var display: *c.Display = c.XOpenDisplay(null).?;
 | 
			
		||||
    const display: *c.Display = c.XOpenDisplay(null).?;
 | 
			
		||||
    defer _ = c.XCloseDisplay(display);
 | 
			
		||||
    const default_screen = c.XDefaultScreen(display);
 | 
			
		||||
    var color = c.XBlackPixel(display, default_screen);
 | 
			
		||||
    var window = c.XCreateSimpleWindow(display, c.XDefaultRootWindow(display), 0, 0, 1, 1, 0, color, color);
 | 
			
		||||
    const color = c.XBlackPixel(display, default_screen);
 | 
			
		||||
    const window = c.XCreateSimpleWindow(display, c.XDefaultRootWindow(display), 0, 0, 1, 1, 0, color, color);
 | 
			
		||||
    defer _ = c.XDestroyWindow(display, window);
 | 
			
		||||
    // Watch will not return
 | 
			
		||||
    if (watch) try watchClip(allocator, display, window, "CLIPBOARD", clip);
 | 
			
		||||
    var result = (try printSelection(allocator, display, window, "CLIPBOARD", "UTF8_STRING", clip)) or
 | 
			
		||||
    const result = (try printSelection(allocator, display, window, "CLIPBOARD", "UTF8_STRING", clip)) or
 | 
			
		||||
        (try printSelection(allocator, display, window, "CLIPBOARD", "STRING", clip));
 | 
			
		||||
    if (!result) return error.ClipboardActionFailed;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +44,7 @@ fn watchClip(allocator: std.mem.Allocator, display: *c.Display, window: c.Window
 | 
			
		|||
    var event_base: c_int = undefined;
 | 
			
		||||
    var error_base: c_int = undefined;
 | 
			
		||||
    var event: c.XEvent = undefined;
 | 
			
		||||
    var bufid = c.XInternAtom(display, bufname, c.False);
 | 
			
		||||
    const bufid = c.XInternAtom(display, bufname, c.False);
 | 
			
		||||
 | 
			
		||||
    _ = c.XFixesQueryExtension(display, &event_base, &error_base);
 | 
			
		||||
    _ = c.XFixesSelectSelectionInput(display, c.XDefaultRootWindow(display), bufid, c.XFixesSetSelectionOwnerNotifyMask);
 | 
			
		||||
| 
						 | 
				
			
			@ -74,10 +72,10 @@ fn printSelection(
 | 
			
		|||
    var ressize: c_ulong = undefined;
 | 
			
		||||
    var restail: c_ulong = undefined;
 | 
			
		||||
    var resbits: c_int = undefined;
 | 
			
		||||
    var bufid = c.XInternAtom(display, bufname, c.False);
 | 
			
		||||
    const bufid = c.XInternAtom(display, bufname, c.False);
 | 
			
		||||
    var fmtid = c.XInternAtom(display, fmtname, c.False);
 | 
			
		||||
    var propid = c.XInternAtom(display, "XSEL_DATA", c.False);
 | 
			
		||||
    var incrid = c.XInternAtom(display, "INCR", c.False);
 | 
			
		||||
    const propid = c.XInternAtom(display, "XSEL_DATA", c.False);
 | 
			
		||||
    const incrid = c.XInternAtom(display, "INCR", c.False);
 | 
			
		||||
    var event: c.XEvent = undefined;
 | 
			
		||||
 | 
			
		||||
    _ = c.XSelectInput(display, window, c.PropertyChangeMask);
 | 
			
		||||
| 
						 | 
				
			
			@ -91,13 +89,13 @@ fn printSelection(
 | 
			
		|||
        _ = c.XGetWindowProperty(display, window, propid, 0, c.LONG_MAX / 4, c.True, c.AnyPropertyType, &fmtid, &resbits, &ressize, &restail, &result);
 | 
			
		||||
        defer _ = c.XFree(result);
 | 
			
		||||
        if (fmtid != incrid)
 | 
			
		||||
            _ = async clip.clipboardChanged(std.mem.span(result)); // TODO: Ensure we don't start queueing these things up
 | 
			
		||||
            _ = try clip.clipboardChanged(std.mem.span(result)); // TODO: Ensure we don't start queueing these things up
 | 
			
		||||
 | 
			
		||||
        if (fmtid == incrid) {
 | 
			
		||||
            ressize = 1;
 | 
			
		||||
            var arena_allocator = std.heap.ArenaAllocator.init(allocator);
 | 
			
		||||
            defer arena_allocator.deinit();
 | 
			
		||||
            var local_allocator = arena_allocator.allocator();
 | 
			
		||||
            const local_allocator = arena_allocator.allocator();
 | 
			
		||||
            var buffer = std.ArrayList(u8).init(local_allocator);
 | 
			
		||||
            defer buffer.deinit();
 | 
			
		||||
            while (ressize > 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +108,7 @@ fn printSelection(
 | 
			
		|||
                //defer _ = c.XFree(result); // Creates double free error, but not sure why
 | 
			
		||||
                try buffer.appendSlice(try std.fmt.allocPrint(local_allocator, "{s}", .{result}));
 | 
			
		||||
            }
 | 
			
		||||
            _ = async clip.clipboardChanged(buffer.items);
 | 
			
		||||
            _ = try clip.clipboardChanged(buffer.items);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    } else // request failed, e.g. owner can't convert to the target format
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1191,7 +1191,7 @@ fn UpdateContents(hwnd: w.HWND) void {
 | 
			
		|||
    // Get a lock on the clipboard
 | 
			
		||||
    if (OpenClipboard(hwnd) > 0) {
 | 
			
		||||
        defer _ = CloseClipboard();
 | 
			
		||||
        var hglb = GetClipboardData(uFormat).?;
 | 
			
		||||
        var hglb = GetClipboardData(uFormat) orelse return;
 | 
			
		||||
        const hnd = @intCast(isize, @ptrToInt(hglb));
 | 
			
		||||
        var lpstr = GlobalLock(hnd).?;
 | 
			
		||||
        defer _ = GlobalUnlock(hnd);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +0,0 @@
 | 
			
		|||
const use_submodules = 1;
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue