hexchat_api/plugin.rs
1use std::ffi::{CString, c_void};
2use crate::{str2cstring, PHEXCHAT};
3use std::ptr;
4use std::cell::RefCell;
5use std::rc::Rc;
6
7// TODO - Currently there's no use for retaining all the data except for the
8// handle. Consider removing the CString fields.
9#[allow(dead_code)]
10struct PluginData {
11 file_name : CString,
12 plugin_name : CString,
13 description : CString,
14 version : CString,
15 handle : *const c_void,
16 removed : bool,
17}
18
19/// Represents a created plugin entry. Plugins that embed other language
20/// interpreters and load plugins written in those languages can have Hexchat
21/// look as if the loaded scripts are actual plugins. By creating a `Plugin`
22/// object for such a script, an entry is made in Hexchat's list of loaded
23/// plugins. When one of these scripts is unloaded, the fictitious plugin entry
24/// can be removed from Hexchat by dropping the associated `Plugin` object.
25///
26#[derive(Clone)]
27pub struct Plugin {
28 data: Rc<RefCell<PluginData>>,
29}
30
31impl Plugin {
32 /// Creates a new plugin entry in Hexchat.
33 /// # Arguments
34 /// `file_name` - The name of the script representing a "plugin".
35 /// `plugin_name` - The name of the plugin script.
36 /// `description` - The plugin script's description.
37 /// `version` - A version string for the plugin script.
38 ///
39 pub fn new(file_name : &str,
40 plugin_name : &str,
41 description : &str,
42 version : &str)
43 -> Plugin
44 {
45 unsafe {
46 let hc = &*PHEXCHAT;
47 let null = ptr::null::<c_void>();
48 let file_name = str2cstring(file_name);
49 let plugin_name = str2cstring(plugin_name);
50 let description = str2cstring(description);
51 let version = str2cstring(version);
52
53 let handle = (hc.c_plugingui_add)(hc,
54 file_name.as_ptr(),
55 plugin_name.as_ptr(),
56 description.as_ptr(),
57 version.as_ptr(),
58 null.cast());
59 let pd = PluginData {
60 file_name,
61 plugin_name,
62 description,
63 version,
64 handle : handle.cast(),
65 removed : false,
66 };
67 Plugin { data: Rc::new(RefCell::new(pd)) }
68 }
69 }
70 /// Removes the plugin entry for the plugin script. This can be used to
71 /// remove a plugin entry, or simply dropping the `Plugin` object will
72 /// cause removal to happen automatically.
73 ///
74 pub fn remove(&self) {
75 let cell = &*self.data;
76 let data = &mut *cell.borrow_mut();
77 if !data.removed {
78 unsafe {
79 let hc = &*PHEXCHAT;
80 (hc.c_plugingui_remove)(hc, data.handle.cast());
81 }
82 data.removed = true;
83 }
84 }
85}
86
87impl Drop for PluginData {
88 /// Removes the entry in Hexchat's plugins list for the `Plugin`.
89 fn drop(&mut self) {
90 if !self.removed {
91 unsafe {
92 let hc = &*PHEXCHAT;
93 (hc.c_plugingui_remove)(hc, self.handle.cast());
94 }
95 }
96 }
97}