![]() |
![]() |
![]() |
![]() |
This chapter contains examples of using the PhAB plugin API to create resource editors. There are two examples:
The following is an example resource editor plugin for editing a string resource. This is taken from the actual PhAB source code. Not shown is the PhAB project which contains this source file and implements the widgets within a picture module.
#include <Pt.h>
#include <Ap.h>
/* Local headers */
#include "rstring.h"
#include "abimport.h"
#include "proto.h"
static int plugin_loading( const char *path );
static void plugin_unloading( void );
static void plugin_frugal_set_data( ResPluginHandle_t handle, int n,
const void *value, const ResPluginFormatData_t *format );
static void plugin_full_set_data( ResPluginHandle_t handle, int n,
const void *value, const ResPluginFormatData_t *format );
static void plugin_frugal_destroy( ResPluginHandle_t handle );
static void plugin_full_destroy( ResPluginHandle_t handle );
static ResPluginHandle_t plugin_frugal_create
( PhABHandle_t phab , const PhABResExportFrugal_t *exp,
const ResPluginFormatData_t *format,
int n_default, const void *default_value,
PtWidget_t *parent,
int n, const void *value );
static ResPluginHandle_t plugin_full_create
( PhABHandle_t phab , const PhABResExportFull_t *exp,
const ResPluginFormatData_t *format,
int n_default, const void *default_value,
PhArea_t *area, char *caption,
int n, const void *value );
static void plugin_full_disable( ResPluginHandle_t handle );
static void plugin_full_block( ResPluginHandle_t handle, int block );
static void plugin_full_to_front( ResPluginHandle_t handle );
static int plugin_full_any_changes( ResPluginHandle_t handle );
static void plugin_full_get_changes( ResPluginHandle_t handle, int *pn, void **pvalue );
static void plugin_full_get_area( ResPluginHandle_t handle, PhArea_t *area );
static void plugin_full_notify( ResPluginAction_t action, void *data );
/* callbacks */
static int plugin_frugal_changed( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo );
static int plugin_full_resize( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo );
static int plugin_full_changed( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo );
static int plugin_full_done( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo );
static void set_state( PluginFullInstance_t *instance, char *value );
static ResPluginFullEditor_t full_editors[1] =
{
{
{ "string",
RES_DATATYPE_STRING,
RESPLUGIN_DATATYPE_VERSION,
plugin_full_set_data,
plugin_full_destroy },
plugin_full_create,
plugin_full_disable,
plugin_full_block,
plugin_full_to_front,
plugin_full_any_changes,
plugin_full_get_changes,
plugin_full_get_area
}
};
static ResPluginFrugalEditor_t frugal_editors[1] =
{
{
{ "string",
RES_DATATYPE_STRING,
RESPLUGIN_DATATYPE_VERSION,
plugin_frugal_set_data,
plugin_frugal_destroy },
plugin_frugal_create,
}
};
static ResPlugin_t tab = {
plugin_loading,
plugin_unloading,
1,
full_editors,
1,
frugal_editors
};
AOInterface_t string_interfaces[] = {
{ "PhAB Resource Editors", RESPLUGIN_VERSION, &tab },
{ 0, 0, 0 }
};
static int loaded_count = 0;
static ApDBase_t *db = NULL;
static int plugin_loading( const char *path ) {
if( loaded_count == 0 && ApAddContext( &AbContext, path ) )
return -1;
db = ApOpenDBase( ABM_string_db );
++loaded_count;
return 0;
}
static void plugin_unloading( void ) {
if( -- loaded_count == 0 ) {
ApCloseDBase( db );
db = NULL;
ApRemoveContext( &AbContext );
}
}
static ResPluginHandle_t plugin_frugal_create
( PhABHandle_t phab , const PhABResExportFrugal_t *exp,
const ResPluginFormatData_t *format,
int n_default, const void *default_value,
PtWidget_t *parent,
int n, const void *value ) {
PtArg_t args[2];
PhRect_t offset = { { -1, -1 }, { -1, -1 } };
PluginFrugalInstance_t *instance;
instance = calloc( 1, sizeof( *instance ) );
if( !instance ) return NULL;
instance->n_default = n_default;
instance->default_value = default_value;
instance->n_master = n;
instance->value_master = value;
instance->phab = phab;
instance->exp = exp;
PtSetArg( &args[0], Pt_ARG_ANCHOR_OFFSETS, &offset, 0 );
PtSetArg( &args[1], Pt_ARG_TEXT_STRING, value, 0 );
instance->frugal = ApCreateWidget( db, "string_frugal", 0, 0, 2, args );
PtAddCallback( instance->frugal, Pt_CB_TEXT_CHANGED, plugin_frugal_changed,
instance );
return ( ResPluginHandle_t ) instance;
}
static void plugin_frugal_set_data( ResPluginHandle_t handle, int n,
const void *value, const ResPluginFormatData_t *format )
{
PluginFrugalInstance_t *instance = ( PluginFrugalInstance_t * ) handle;
instance->n_master = n;
instance->value_master = value;
PtSetResource( instance->frugal, Pt_ARG_TEXT_STRING, value, 0 );
}
static int plugin_frugal_changed( PtWidget_t *widget, void *data,
PtCallbackInfo_t *cbinfo ) {
PluginFrugalInstance_t *instance = ( PluginFrugalInstance_t * ) data;
char *p;
PtGetResource( widget, Pt_ARG_TEXT_STRING, &p, 0 );
instance->n_master = strlen( p );
instance->value_master = strdup( p );
if( instance->exp->common.apply( instance->phab, instance->n_master,
instance->value_master ) ) {
/* we matched the default */
free( instance->value_master );
instance->value_master = instance->default_value;
instance->n_master = instance->n_default;
}
return Pt_CONTINUE;
}
static void plugin_frugal_destroy( ResPluginHandle_t handle )
{
free( ( PluginFrugalInstance_t * ) handle );
}
static ResPluginHandle_t plugin_full_create
( PhABHandle_t phab , const PhABResExportFull_t *exp,
const ResPluginFormatData_t *format,
int n_default, const void *default_value,
PhArea_t *area, char *caption,
int n, const void *value )
{
PluginFullInstance_t *instance;
PtWidget_t *parent;
PhRect_t offset = { { 0, 0 }, { 0, 0 } };
PhArea_t tarea;
PtArg_t args[1];
int start = 0, end = n;
instance = calloc( 1, sizeof( *instance ) );
if( !instance ) return NULL;
instance->n_default = n_default;
instance->default_value = default_value;
instance->n_master = n;
instance->value_master = value;
instance->phab = phab;
instance->exp = exp;
if( !area ) {
PhRect_t rect;
PhWindowQueryVisible( 0, 0, 0, &rect );
tarea.pos.x = rect.ul.x + 100;;
tarea.pos.y = rect.ul.y + 100;
tarea.size.w = 340;
tarea.size.h = 150;
area = &tarea;
}
instance->convenience_handle = exp->create_window( area, caption, 0, &parent,
plugin_full_notify, instance );
PtSetParentWidget( parent );
PtSetArg( &args[0], Pt_ARG_ANCHOR_OFFSETS, &offset, 0 );
instance->full= ApCreateWidgetFamily( db, "string_full_container", 0, 0, 1, args );
instance->full_widget = PtWidgetChildFront( instance->full );
PtAddCallback( instance->full, Pt_CB_RESIZE, plugin_full_resize, instance );
PtAddCallback( instance->full_widget, Pt_CB_TEXT_CHANGED, plugin_full_changed, instance );
PtAddCallback( instance->full_widget, Pt_CB_ACTIVATE, plugin_full_done, instance );
PtSetResource( instance->full_widget, Pt_ARG_TEXT_STRING, value, 0 );
PtTextSetSelection( instance->full_widget, &start, &end );
PtRealizeWidget( instance->full );
set_state( instance, value );
return ( ResPluginHandle_t ) instance;
}
static void plugin_full_destroy( ResPluginHandle_t handle )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
instance->exp->destroy( instance->convenience_handle );
free( instance );
}
static void plugin_full_disable( ResPluginHandle_t handle )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
PtArg_t args[3];
instance->disabled = 1;
PtSetArg( &args[0], Pt_ARG_FLAGS, Pt_GHOST|Pt_BLOCKED, Pt_GHOST|Pt_BLOCKED );
PtSetArg( &args[1], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NOINPUT, 0 );
PtSetArg( &args[2], Pt_ARG_CURSOR_OVERRIDE, 1, 0 );
PtSetResources( instance->full, 3, args );
PtSetResource( instance->full_widget, Pt_ARG_FLAGS, Pt_GHOST|Pt_BLOCKED,
Pt_GHOST|Pt_BLOCKED );
instance->exp->set_state( instance->convenience_handle, RESPLUGIN_STATE_DISABLED );
}
static void plugin_full_block( ResPluginHandle_t handle, int block )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
instance->exp->set_state( instance->convenience_handle,
block ? RESPLUGIN_STATE_BLOCKED : RESPLUGIN_STATE_UNBLOCKED );
}
static int plugin_full_any_changes( ResPluginHandle_t handle )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
char *p;
PtGetResource( instance->full_widget, Pt_ARG_TEXT_STRING, &p, 0 );
if( !strcmp( p, instance->value_master ) ) return RESPLUGIN_NO_CHANGES;
return RESPLUGIN_CHANGES;
}
static void plugin_full_get_changes( ResPluginHandle_t handle, int *pn, void **pvalue )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
char *p;
PtGetResource( instance->full_widget, Pt_ARG_TEXT_STRING, &p, 0 );
*pn = strlen( p );
*pvalue = strdup( p );
}
static void plugin_full_get_area( ResPluginHandle_t handle, PhArea_t *area )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
instance->exp->get_area( instance->convenience_handle, area );
}
static void plugin_full_to_front( ResPluginHandle_t handle )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
instance->exp->to_front( instance->convenience_handle );
}
static void plugin_full_set_data( ResPluginHandle_t handle, int n, const void *value,
const ResPluginFormatData_t *format ) {
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
int start = 0, end = n;
PtSetResource( instance->full_widget, Pt_ARG_TEXT_STRING, value, 0 );
PtTextSetSelection( instance->full_widget, &start, &end );
instance->n_master = n;
instance->value_master = value;
set_state( instance, value );
if( instance->disabled ) {
PtArg_t args[3];
instance->disabled = 0;
PtSetArg( &args[0], Pt_ARG_FLAGS, 0, Pt_GHOST|Pt_BLOCKED );
PtSetArg( &args[1], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_INHERIT, 0 );
PtSetArg( &args[2], Pt_ARG_CURSOR_OVERRIDE, 0, 0 );
PtSetResources( instance->full, 3, args );
PtSetResource( instance->full_widget, Pt_ARG_FLAGS, 0, Pt_GHOST|Pt_BLOCKED );
}
}
static int plugin_full_resize( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
PtContainerCallback_t *cb = cbinfo->cbdata;
if( cb->old_dim.w != cb->new_dim.w || cb->old_dim.h != cb->new_dim.h ) {
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) data;
PhDim_t dim;
PhPoint_t pos;
/* center the instance->full_widget */
PtWidgetDim( instance->full_widget, &dim );
pos.x = ( cb->new_dim.w - dim.w ) / 2;
pos.y = ( cb->new_dim.h - dim.h ) / 2;
PtSetResource( instance->full_widget, Pt_ARG_POS, &pos, 0 );
}
return Pt_CONTINUE;
}
static int plugin_full_changed( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) data;
char *p;
PtGetResource( widget, Pt_ARG_TEXT_STRING, &p, 0 );
set_state( instance, p );
return Pt_CONTINUE;
}
static void get_value_and_apply( PluginFullInstance_t *instance ) {
char *p;
PtGetResource( instance->full_widget, Pt_ARG_TEXT_STRING, &p, 0 );
instance->n_master = strlen( p );
instance->value_master = strdup( p );
if( instance->exp->common.apply( instance->phab, instance->n_master,
instance->value_master ) ) {
/* we matched the default */
free( instance->value_master );
instance->value_master = instance->default_value;
instance->n_master = instance->n_default;
}
}
static int plugin_full_done( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) data;
get_value_and_apply( instance );
instance->exp->closing( instance->phab );
instance->exp->destroy( instance->convenience_handle );
free( instance );
return Pt_CONTINUE;
}
static void plugin_full_notify( ResPluginAction_t action, void *notify_data ) {
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) notify_data;
switch( action ) {
case RESPLUGIN_ACTION_APPLY: {
if( instance->state != RESPLUGIN_STATE_MATCH_MASTER &&
instance->state != RESPLUGIN_STATE_MATCH_DEFAULT_MASTER ) {
get_value_and_apply( instance );
set_state( instance, instance->value_master );
}
}
break;
case RESPLUGIN_ACTION_CLOSE: {
instance->exp->closing( instance->phab );
instance->exp->destroy( instance->convenience_handle );
free( instance );
}
break;
case RESPLUGIN_ACTION_DEFAULT: {
PtSetResource( instance->full_widget, Pt_ARG_TEXT_STRING,
instance->default_value, 0 );
set_state( instance, instance->default_value );
}
break;
}
}
static void set_state( PluginFullInstance_t *instance, char *value ) {
if( !strcmp( value, instance->default_value ) ) {
if( strcmp( value, instance->value_master ) )
instance->state = RESPLUGIN_STATE_MATCH_DEFAULT;
else instance->state = RESPLUGIN_STATE_MATCH_DEFAULT_MASTER;
}
else {
if( strcmp( value, instance->value_master ) )
instance->state = RESPLUGIN_STATE_NO_MATCH;
else instance->state = RESPLUGIN_STATE_MATCH_MASTER;
}
instance->exp->set_state( instance->convenience_handle, instance->state );
}
The following is an example of using an external application as a resource editor in PhAB. We will use ped to edit the Pt_ARG_TEXT_STRING resource for the PtButton widget.
To use this example, compile the two files listed below, external_multi.h and external_multi.c, into a DLL named external_multi.so.Copy the external_multi.so file into the plugins/resource directory below the location that contains PhAB's executable (usually /usr/photon/appbuilder/plugins/resource).Edit the res_editors.def in the PhAB executable directory to contain the lines:
e=external_multi p= F=multi@external_multi.so
Edit the file def_res.def in the same directory to contain the line:
external_multi
Edit the ptpalette.pal file in the same directory to specify external_multi as the resource editor for Pt_ARG_TEXT_STRING for the PtButton widget. To do this, in the PtButton section of the file, change the Pt_ARG_TEXT_STRING line to:
r=Pt_ARG_TEXT_STRING,Button Text,3011,3002,0,multi/external_multi,NULL
Code listing for external_multi.h
#ifndef __ALREADY_INCLUDED_H
#define __ALREADY_INCLUDED_H
#include <photon/res_plugin_api.h>
#include <aoi/aoi.h>
#include <pthread.h>
typedef struct {
int n_master;
void *value_master;
int n_default;
void *default_value;
PhABHandle_t phab;
PhABResExportFull_t *exp;
int pid, phab_waiting;
char *path;
pthread_t monitor;
} PluginFullInstance_t;
#endif
Code listing for external_multi.c
#include <Pt.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/netmgr.h>
#include <time.h>
#include <signal.h>
/* Local headers */
#include "external_multi.h"
static int plugin_loading( const char *path );
static void plugin_unloading( void );
static void plugin_full_set_data( ResPluginHandle_t handle, int n, const void *value,
const ResPluginFormatData_t *format );
static void plugin_full_destroy( ResPluginHandle_t handle );
static ResPluginHandle_t plugin_full_create
( PhABHandle_t phab , const PhABResExportFull_t *exp,
const ResPluginFormatData_t *format,
int n_default, const void *default_value,
PhArea_t *area, char *caption,
int n, const void *value );
static void plugin_full_disable( ResPluginHandle_t handle );
static void plugin_full_block( ResPluginHandle_t handle, int block );
static void plugin_full_to_front( ResPluginHandle_t handle );
static int plugin_full_any_changes( ResPluginHandle_t handle );
static void plugin_full_get_changes( ResPluginHandle_t handle, int *pn, void **pvalue );
static void plugin_full_get_area( ResPluginHandle_t handle, PhArea_t *area );
static void child_exit( int sig );
static void *monitor_f( void * data );
static void get_changes_from_file( PluginFullInstance_t *instance, int *pn,
char **value );
static void apply_from_file( PluginFullInstance_t *instance );
static void emit_wm_event( PluginFullInstance_t *instance, unsigned long event_type );
static void was_file_changed( PluginFullInstance_t *instance, int *modification_time );
static ResPluginFullEditor_t full_editors[1] =
{
{
{ "multi",
RES_DATATYPE_MULTI,
RESPLUGIN_DATATYPE_VERSION,
plugin_full_set_data,
plugin_full_destroy },
plugin_full_create,
plugin_full_disable,
plugin_full_block,
plugin_full_to_front,
plugin_full_any_changes,
plugin_full_get_changes,
plugin_full_get_area
}
};
static ResPlugin_t tab = {
plugin_loading,
plugin_unloading,
1,
full_editors,
0,
NULL
};
AOInterface_t interfaces[] = {
{ "PhAB Resource Editors", RESPLUGIN_VERSION, &tab },
{ 0, 0, 0 }
};
static int plugin_loading( const char *path ) {
signal( SIGCHLD, child_exit );
return 0;
}
static void plugin_unloading( void ) {
}
static ResPluginHandle_t plugin_full_create
( PhABHandle_t phab , const PhABResExportFull_t *exp,
const ResPluginFormatData_t *format,
int n_default, const void *default_value,
PhArea_t *area, char *caption,
int n, const void *value )
{
PluginFullInstance_t *instance;
FILE *fp;
char path[PATH_MAX];
time_t t;
char *argv[3];
time( &t );
/* put the data in a file */
sprintf( path, "/tmp/%ld.txt", (long) t );
fp = fopen( path, "w" );
if( !fp ) return NULL;
if( value ) fwrite( (char*)value, 1, n, fp );
fclose( fp );
instance = calloc( 1, sizeof( *instance ) );
if( !instance ) return NULL;
instance->n_default = n_default;
instance->default_value = default_value;
instance->n_master = n;
instance->value_master = value;
instance->phab = phab;
instance->exp = exp;
argv[0] = "ped";
argv[1] = path;
argv[2] = NULL;
instance->pid = spawnp( argv[0], 0, NULL, NULL, argv, NULL );
if( instance->pid == -1 ) {
free( instance );
unlink( path );
return NULL;
}
instance->path = strdup( path );
pthread_create( &instance->monitor, NULL, monitor_f, (void*) instance );
return ( ResPluginHandle_t ) instance;
}
static void plugin_full_destroy( ResPluginHandle_t handle )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
if( instance->pid != -1 ) {
/* the child process is still alive, but the data inside has been asked
for already */
kill( instance->pid, SIGTERM );
}
pthread_cancel( instance->monitor );
pthread_detach( instance->monitor );
unlink( instance->path );
free( instance->path );
free( instance );
}
static void plugin_full_disable( ResPluginHandle_t handle )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
/* the changes inside the editor has already been taken into account */
/* close the external application if still open */
/* we need to do this because we cannot put a new data into the external
application ( ped ), without re-spawing it */
if( instance->pid != -1 ) {
kill( instance->pid, SIGTERM );
instance->pid = -1;
pthread_cancel( instance->monitor );
pthread_detach( instance->monitor );
}
/* we have a disabled instance ( the instance pointer still valid ),
but the pid and monitor have been destroyed */
}
static void plugin_full_block( ResPluginHandle_t handle, int block )
{
}
static int plugin_full_any_changes( ResPluginHandle_t handle )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
if ( instance->pid == -1 ) return RESPLUGIN_NO_CHANGES;
else {
emit_wm_event( instance, Ph_WM_TOFRONT );
emit_wm_event( instance, Ph_WM_CLOSE );
instance->phab_waiting = 1;
return RESPLUGIN_WAIT;
}
}
static void plugin_full_get_changes( ResPluginHandle_t handle, int *pn, void **pvalue )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
/* the changes are in the instance->path */
get_changes_from_file( instance, pn, ( char ** ) pvalue );
}
static void plugin_full_get_area( ResPluginHandle_t handle, PhArea_t *area )
{
/* not used, let the external editor memorize/restore its own area */
}
static void plugin_full_to_front( ResPluginHandle_t handle )
{
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
emit_wm_event( instance, Ph_WM_TOFRONT );
}
static void plugin_full_set_data( ResPluginHandle_t handle, int n, const void *value,
const ResPluginFormatData_t *format ) {
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) handle;
FILE *fp;
instance->n_master = n;
instance->value_master = value;
/* re-spawn the external application and the monitor thread */
fp = fopen( instance->path, "w" );
if( value ) fwrite( (char*)value, 1, n, fp );
fclose( fp );
instance->pid = spawnl( P_NOWAIT, "ped", "ped", instance->path, NULL );
pthread_create( &instance->monitor, NULL, monitor_f, (void*) instance );
}
static void child_exit( int sig ) {
int status;
wait( &status );
}
static void *monitor_f( void * data ) {
PluginFullInstance_t *instance = ( PluginFullInstance_t * ) data;
int mod = 0;
for( ; ; ) {
/* check if instance->pid still exists */
if( kill( instance->pid, 0 ) == -1 ) {
/* the child has exited */
instance->pid = -1;
if( instance->phab_waiting ) {
int n, answer;
char *value;
get_changes_from_file( instance, &n, &value );
if( n == instance->n_master && !memcmp( value,
instance->value_master,
n ) )
answer = RESPLUGIN_NO_CHANGES;
else answer = RESPLUGIN_CHANGES;
PtEnter( Pt_EVENT_PROCESS_ALLOW );
instance->exp->answer_changes( instance->phab, answer, n, value );
/* the answer_changes() is implying that the editor has been closed */
PtLeave( Pt_EVENT_PROCESS_ALLOW );
}
else {
/* check the modification time on the file again,
because maybe the user did a Exit->Save or not->Save */
was_file_changed( instance, &mod );
PtEnter( Pt_EVENT_PROCESS_ALLOW );
instance->exp->closing( instance->phab );
PtLeave( Pt_EVENT_PROCESS_ALLOW );
}
unlink( instance->path );
free( instance->path );
free( instance );
pthread_detach( pthread_self() );
return NULL;
}
/* check if the instance->path has changed */
was_file_changed( instance, &mod );
delay( 200 );
}
pthread_detach( pthread_self() );
return NULL;
}
static void was_file_changed( PluginFullInstance_t *instance, int *modification_time ) {
struct stat st;
if( stat( instance->path, &st ) == 0 ) {
if( *modification_time != st.st_mtime ) {
if( *modification_time ) {
/* the file was changed - call into phab with the apply method */
apply_from_file( instance );
}
*modification_time = st.st_mtime;
}
}
}
static void get_changes_from_file( PluginFullInstance_t *instance, int *pn,
char **value ) {
FILE *fp;
int n;
char *v;
fp = fopen( instance->path, "r" );
if( !fp ) return;
fseek( fp, 0, SEEK_END );
n = ftell( fp );
fseek( fp, 0, SEEK_SET );
v = malloc( n + 1 );
fread( v, 1, n, fp );
v[ n ] = 0;
fclose( fp );
*pn = n;
*value = v;
}
static void apply_from_file( PluginFullInstance_t *instance ) {
int n;
char *values;
get_changes_from_file( instance, &n, &values );
instance->n_master = n;
instance->value_master = values;
PtEnter( Pt_EVENT_PROCESS_ALLOW );
if( instance->exp->common.apply( instance->phab, instance->n_master,
instance->value_master ) ) {
/* we matched the default */
free( instance->value_master );
instance->value_master = instance->default_value;
instance->n_master = instance->n_default;
}
PtLeave( Pt_EVENT_PROCESS_ALLOW );
}
static PhConnectId_t get_connect_id( pid_t pid )
{
PhConnectInfo_t buf;
PhConnectId_t id = 0;
while ((id = PhGetConnectInfo(id, &buf)) != -1
&& (buf.pid != pid ||
ND_NODE_CMP(buf.nid, ND_LOCAL_NODE)))
++id;
return id;
}
static void emit_wm_event( PluginFullInstance_t *instance, unsigned long event_type ) {
PhWindowEvent_t event;
PhConnectId_t connection_id;
connection_id = get_connect_id( instance->pid );
memset( &event, 0, sizeof (event) );
event.event_f = event_type;
PtForwardWindowTaskEvent( connection_id, &event );
}
![]() |
![]() |
![]() |
![]() |