From: Anders L. <an...@ho...> - 2000-09-14 21:20:49
|
Hi, This is a patch that hooks an application menu to shift click. It's probably quite a mess, because I have no experience in programming. Any advice on programming do's and do not's would be great anyway. That is, if you haven't got better things to do than tipping-off programming illiterates. mvh. Anders Lundmark It reads "$HOME/Choices/ROX-Filer/appstartrc" for configuration. It's in the format: Filetype:Lable1=arguments1:Lable2=arguments2; @ expands to path/filename and % to filename. Like this: C program text:Xemacs=xemacs @:PICO=xterm -title "PICO reading "@ -e pico %:Compile=gcc -O2 -o %.out %; ASCII text:Nedit=nedit %:PICO=xterm -title "This is the file "@" PICO says!" -e pico %; Bourne shell script:Nedit=nedit %; English text:Abiword=abiword %; directory:tar.gz=tar -czf %.tar.gz %:tar.Z=tar -cZf %.tar.Z %; RPM:Install=rpm -U %:List contents=sh -c "rpm -qpl "%"|xmessage -geometry 400x600 -file -"; gzip:UnTar=tar -xzf %:List files=sh -c "tar -tzf "%"|xmessage -geometry 400x600 -file -"; diff -c -r -N /home/anders/rox-0.1.27/ROX-Filer/src/Makefile.in /home/anders/rox-0.1.27p/ROX-Filer/src/Makefile.in *** /home/anders/rox-0.1.27/ROX-Filer/src/Makefile.in Thu Aug 24 17:56:31 2000 --- /home/anders/rox-0.1.27p/ROX-Filer/src/Makefile.in Thu Aug 24 09:00:24 2000 *************** *** 20,32 **** run.c mount.c options.c choices.c gtksavebox.c type.c action.c \ collection.c fscache.c dir.c minibuffer.c modechange.c find.c \ i18n.c rox_gettext.c remote.c display.c pinboard.c toolbar.c \ ! panel.c bind.c OBJECTS = main.o filer.o support.o gui_support.o pixmaps.o menu.o dnd.o \ run.o mount.o options.o choices.o gtksavebox.o type.o action.o \ collection.o fscache.o dir.o minibuffer.o modechange.o find.o \ i18n.o rox_gettext.o remote.o display.o pinboard.o toolbar.o \ ! panel.o bind.o ############ Things to keep the same --- 20,32 ---- run.c mount.c options.c choices.c gtksavebox.c type.c action.c \ collection.c fscache.c dir.c minibuffer.c modechange.c find.c \ i18n.c rox_gettext.c remote.c display.c pinboard.c toolbar.c \ ! panel.c bind.c appmenu.c OBJECTS = main.o filer.o support.o gui_support.o pixmaps.o menu.o dnd.o \ run.o mount.o options.o choices.o gtksavebox.o type.o action.o \ collection.o fscache.o dir.o minibuffer.o modechange.o find.o \ i18n.o rox_gettext.o remote.o display.o pinboard.o toolbar.o \ ! panel.o bind.o appmenu.o ############ Things to keep the same diff -c -r -N /home/anders/rox-0.1.27/ROX-Filer/src/appmenu.c /home/anders/rox-0.1.27p/ROX-Filer/src/appmenu.c *** /home/anders/rox-0.1.27/ROX-Filer/src/appmenu.c Thu Jan 1 01:00:00 1970 --- /home/anders/rox-0.1.27p/ROX-Filer/src/appmenu.c Thu Aug 24 17:39:41 2000 *************** *** 0 **** --- 1,367 ---- + /* appMenu */ + #include <unistd.h> + #include <stdio.h> + #include <string.h> + #include <stdlib.h> + #include <gtk/gtk.h> + #include <glib.h> + #include "support.h" + #include "main.h" + #define BUFFERSIZE 256 + #define MAX_LIST_ENTRIES 15 /* Max nr of commands/filetype and max nr of args/command. */ + + typedef struct { + char *commandList[MAX_LIST_ENTRIES]; + int nbrEntries; + } CML; + + typedef struct { + char *argv[MAX_LIST_ENTRIES]; + char *label; + char *dir; + } PCM; + + CML *findMatchingEntryInFile( char *path, char *string); + char *getCommandOutput( char *command, char *path); + PCM *parseCommand(char *cmd, char *fileName); + void make_cmd_button( PCM *data); + gboolean bError(int err); + char *ptrError(int err); + static gint run_program_cb( PCM *data); + GtkWidget *menu; + + gboolean appMenu( char *fileArgument) + { + PCM *parsedCommand; + CML *appList; + char *command = "file -b "; /* Command line to call file. */ + char *assocFile = "/Choices/ROX-Filer/appstartrc"; /* Preferences. */ + char *envVar = "HOME"; + char *fileCmdError = "can't stat"; + char *assocFilePath; + char *fileType; + char *dir; + char *dirEnd; + size_t stringLength; + int count = 0; + + /* Determine file type. */ + + fileType = getCommandOutput( command, fileArgument); + if ( (strncmp( fileType, fileCmdError, 10) == 0) || fileType == NULL) + return( bError( 1)); + + /* Get specified commands. */ + + stringLength = strlen(getenv(envVar)) + strlen(assocFile) + 1; + if( (assocFilePath = ( char *)malloc( stringLength * sizeof(char))) == NULL) + return( bError(2)); + + strcpy( assocFilePath, ( getenv( envVar))); + strcat( assocFilePath, assocFile); + appList = findMatchingEntryInFile( assocFilePath, fileType); + free( assocFilePath); + free( fileType); + if( appList == NULL) + return FALSE; + + /* Dir stuff for spawn_full */ + + dirEnd = strrchr( fileArgument, '/'); + stringLength = dirEnd - fileArgument + 1; + dir = (char *)malloc(( stringLength + 1) * sizeof(char)); + strncpy( dir, fileArgument, stringLength); + *(dir + stringLength) = '\0'; + + /* No menu if only one associated program. */ + + if( appList->nbrEntries == 0) + { + parsedCommand = parseCommand( appList->commandList[count], fileArgument); + free( appList->commandList[count]); + if( parsedCommand == NULL) + return FALSE; + spawn_full( parsedCommand->argv, dir); + return TRUE; + } + + /* Make meny. */ + + menu = gtk_menu_new(); + + /* Make menu items. */ + + for( count = 0; count <= appList->nbrEntries; count++) + { + parsedCommand = parseCommand( appList->commandList[count], fileArgument); + parsedCommand->dir = dir; + free( appList->commandList[count]); + if( parsedCommand == NULL) + return FALSE; + make_cmd_button( parsedCommand); + } + + gtk_signal_connect_object(GTK_OBJECT(menu), "deactivate", + + /* Is this freeing memory ? */ + + GTK_SIGNAL_FUNC(gtk_object_unref), (gpointer)menu); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0); + return TRUE; + } + + /* Funktioner. */ + + /* Add to menu. */ + + void make_cmd_button( PCM *data) + { + GtkWidget *item; + + item = gtk_menu_item_new_with_label( data->label); + gtk_menu_append(GTK_MENU(menu), item); + gtk_signal_connect_object(GTK_OBJECT(item), "activate", + GTK_SIGNAL_FUNC(run_program_cb), (gpointer)data); + gtk_widget_show(item); + } + + static gint run_program_cb(PCM *data) + { + spawn_full( data->argv, data->dir); + return TRUE; + } + + /* Get filetype from file. */ + + char *getCommandOutput( char *command, char *path) + { + char buffer[BUFFERSIZE]; + FILE *pipeFCommand; + char *cmd; + char *returnStringPtr; + size_t stringLength; + + stringLength = strlen(command) + strlen(path); + if(( cmd = ( char *)malloc((stringLength + 1)* sizeof(char))) == NULL) + return( ptrError(2)); + strcpy( cmd, command); + strcat( cmd, path); + + if(( pipeFCommand = popen( cmd, "r")) == NULL) + { + free( cmd); + return( ptrError(4)); + } + + free( cmd); + fgets( buffer, BUFFERSIZE, pipeFCommand ); + pclose(pipeFCommand); + stringLength = strlen(buffer); + if((returnStringPtr = (char *)malloc( ( stringLength +1) * sizeof( char))) == NULL) + return( ptrError(2)); + strcpy( returnStringPtr, buffer); + returnStringPtr[stringLength - 1] = '\0'; + + return returnStringPtr; + } + + + /* Return a structure with list and nr. of commands. */ + + CML *findMatchingEntryInFile( char *path, char *string) + { + CML *commands; + FILE *assocFp; + char buffer[BUFFERSIZE]; + char *stringPickup; + char *stringPickupEnd; + char *commandString; + int separator = ':'; + int terminator = ';'; + size_t stringLength; + int count = 0; + + if(( assocFp = fopen( path, "r")) == NULL) + return((CML *)ptrError(1)); + + while( feof(assocFp) == 0) + { + fgets( buffer, BUFFERSIZE, assocFp); + + stringPickup = strchr( buffer, separator); + if ( stringPickup != NULL) + { + stringLength = stringPickup - buffer; + + if (( strncmp( buffer, string, stringLength)) == 0) + { + if(( commands = malloc( sizeof( CML))) == NULL) + { + fclose(assocFp); + return(( CML *)ptrError(2)); + } + + while ( *stringPickup != ';' && count < MAX_LIST_ENTRIES) + { + ++stringPickup; + if(( stringPickupEnd = strchr( stringPickup, separator)) == NULL) + { + if(( stringPickupEnd = strchr( stringPickup, terminator)) == NULL) + { + fclose(assocFp); + return(( CML *)ptrError(3)); + } + } + + stringLength = stringPickupEnd - stringPickup; + if(( commandString = (char *)malloc( (stringLength +1) * sizeof(char))) == NULL) + { + fclose(assocFp); + return(( CML *)ptrError(2)); + } + + strncpy( commandString, stringPickup, stringLength); + *(commandString + stringLength) = '\0'; + commands->commandList[count] = commandString; + commands->nbrEntries = count; + stringPickup = stringPickupEnd; + count = count + 1; + } + + fclose(assocFp); + return commands; + } + } + } + + sprintf( buffer ,"A matching entry for:\n\"%s\"\nwas not found in file %s.\n", string, path); + stringLength = strlen(buffer); + write( to_error_log, buffer, stringLength); + fclose(assocFp); + return NULL; + } + + /* Make menu label and argument list. + @ expands to full path filename, + % to filename without path. */ + + PCM *parseCommand(char *cmd, char *fileName) + { + PCM *parsedCommand; + size_t offset; + char *stringEnd; + char *pickup; + char *fileNoPath; + size_t stringLength; + char buffer[256]; + int count = 0; + + parsedCommand = malloc( sizeof( PCM)); + fileNoPath = ( strrchr( fileName, '/') + 1); + + /* Lable stuff */ + + if(( pickup = strchr(cmd, '=')) == NULL) + return (( PCM *)ptrError( 3)); + stringLength = pickup - cmd; + if(( parsedCommand->label = (char *)malloc( stringLength * sizeof( char))) == NULL) + return (( PCM *)ptrError( 2)); + strncpy( parsedCommand->label, cmd, stringLength); + *( parsedCommand->label + stringLength) = '\0'; + + pickup = pickup +1; + *buffer = '\0'; + + while( (*pickup != '\0') && (count <= ( MAX_LIST_ENTRIES -2))) + { + offset = strcspn( pickup, " %@\""); + switch(*(pickup + offset)) + { + case ' ': + { + if( *(pickup + offset - 1) != ' ' ) + { + strncat( buffer, pickup, offset); + if(( parsedCommand->argv[count] = (char *)malloc(( strlen( buffer) + 1) * sizeof( char))) == NULL) + return (( PCM *)ptrError( 2)); + strcpy(parsedCommand->argv[count], buffer); + pickup = pickup + offset; + count = count +1; + } + *buffer = '\0'; + pickup = pickup + 1; + break; + } + case '\"': + { + strncat( buffer, pickup, offset); + pickup = pickup + offset + 1; + stringEnd = strchr( pickup, '\"'); + strncat( buffer, pickup, (stringEnd - pickup)); + pickup = stringEnd +1; + break; + } + case '@': + { + strncat( buffer, pickup, offset); + strcat(buffer, fileName); + pickup = pickup + offset +1; + break; + } + case '%': + { + strncat( buffer, pickup, offset); + strcat(buffer, fileNoPath); + pickup = pickup + offset +1; + break; + } + default: + { + strncat( buffer, pickup, offset); + pickup = pickup + offset; + } + } + } + if(( parsedCommand->argv[count] = (char *)malloc(( strlen( buffer) + 1) * sizeof( char))) == NULL) + return (( PCM *)ptrError( 2)); + strcpy(parsedCommand->argv[count], buffer); + parsedCommand->argv[count + 1] = NULL; + return parsedCommand; + } + + gboolean bError(int err) + { + switch( err) + { + case 1: + write( to_error_log, "Filetyping failed.", ( 18 * sizeof( char))); + return FALSE; + case 2: + write( to_error_log, "Memory allocation error", ( 23 * sizeof( char))); + return FALSE; + default: + return FALSE; + } + } + + char *ptrError(int err) + { + switch( err) + { + case 1: + write( to_error_log, "No appstartrc file was found", ( 28 * sizeof( char))); + return NULL; + case 2: + write( to_error_log, "Memory allocation error", ( 23 * sizeof( char))); + return NULL; + case 3: + write( to_error_log, "Error reading appstartrc.", ( 25 * sizeof( char))); + return NULL; + case 4: + write( to_error_log, "The command file was not found.", ( 31 * sizeof( char))); + return NULL; + default: + return NULL; + } + } + diff -c -r -N /home/anders/rox-0.1.27/ROX-Filer/src/appmenu.h /home/anders/rox-0.1.27p/ROX-Filer/src/appmenu.h *** /home/anders/rox-0.1.27/ROX-Filer/src/appmenu.h Thu Jan 1 01:00:00 1970 --- /home/anders/rox-0.1.27p/ROX-Filer/src/appmenu.h Tue Aug 22 21:59:24 2000 *************** *** 0 **** --- 1,11 ---- + + + #ifndef _APPMENU_H + #define _APPMENU_H + + + /* Prototypes */ + + gboolean appMenu( char *fileArgument); + + #endif /* _APPMENU_H */ diff -c -r -N /home/anders/rox-0.1.27/ROX-Filer/src/run.c /home/anders/rox-0.1.27p/ROX-Filer/src/run.c *** /home/anders/rox-0.1.27/ROX-Filer/src/run.c Thu Aug 24 17:56:31 2000 --- /home/anders/rox-0.1.27p/ROX-Filer/src/run.c Thu Aug 24 06:12:41 2000 *************** *** 40,51 **** --- 40,55 ---- #include "pinboard.h" #include "panel.h" + #include "appmenu.h" + /* Static prototypes */ static void write_data(gpointer data, gint fd, GdkInputCondition cond); static gboolean follow_symlink(char *full_path, FilerWindow *filer_window); static gboolean open_file(guchar *path, MIME_type *type); static void app_show_help(char *path); + gboolean appMenu( char *fileArgument); + typedef struct _PipedData PipedData; struct _PipedData *************** *** 210,216 **** run_app(full_path); return TRUE; } ! if (item->flags & ITEM_FLAG_MOUNT_POINT && edit) { GList *paths; --- 214,226 ---- run_app(full_path); return TRUE; } ! ! if (item->flags & ITEM_FLAG_APPDIR && edit) ! { ! filer_change_to(filer_window, full_path, NULL); ! return TRUE; ! } ! if (item->flags & ITEM_FLAG_MOUNT_POINT && edit) { GList *paths; *************** *** 221,226 **** --- 231,239 ---- if (item->flags & ITEM_FLAG_MOUNTED) return TRUE; } + + if (filer_window && edit) + return appMenu(full_path); if (filer_window) filer_change_to(filer_window, full_path, NULL); *************** *** 245,251 **** return FALSE; } } ! return open_file(full_path, edit ? &text_plain : item->mime_type); default: --- 258,268 ---- return FALSE; } } ! if( edit) ! { ! return appMenu(full_path); ! } ! return open_file(full_path, edit ? &text_plain : item->mime_type); default: _________________________________________________________________________ Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com. Share information about yourself, create your own public profile at http://profiles.msn.com. |