#include "FvwmIconMan.h" #include "../../fvwm/module.h" static int fd_width; static FILE *console = NULL; static char *VERSION = "0.4"; #if !defined (__GNUC__) || defined (PRINT_DEBUG) char *actionNames[] = { "click1", "click2", "click3", "select" }; #endif typedef enum { READ_LINE = 1, READ_OPTION = 2, READ_ARG = 4, READ_REST_OF_LINE = 12 } ReadOption; void Free (void *p) { if (p != NULL) free (p); } static int iswhite (char c) { if (c == ' ' || c == '\t' || c == '\0') return 1; return 0; } static void skip_space (char **p) { while (**p == ' ' || **p == '\t') (*p)++; } #if FVWM_VERSION == 1 static FILE *config_fp = NULL; #endif static int init_config_file (char *file) { #if FVWM_VERSION == 1 if ((config_fp = fopen (file, "r")) == NULL) { ConsoleMessage ("Couldn't open file: %s\n", file); return 0; } #endif return 1; } static void close_config_file (void) { #if FVWM_VERSION == 1 if (config_fp) fclose (config_fp); #endif } static int GetConfigLineWrapper (int *fd, char **tline) { #if FVWM_VERSION == 1 static char buffer[1024]; char *temp; if (fgets (buffer, 1024, config_fp)) { *tline = buffer; temp = strchr (*tline, '\n'); if (temp) { *temp = '\0'; } else { fprintf (stderr, "line too long\n"); exit (1); } return 1; } #else char *temp; GetConfigLine (fd, tline); if (*tline) { temp = strchr (*tline, '\n'); if (temp) { *temp = '\0'; } return 1; } #endif return 0; } static char *read_next_cmd (ReadOption flag) { static ReadOption status; static char *buffer; static char *retstring, displaced, *cur_pos; retstring = NULL; if (flag != READ_LINE && !(flag & status)) return NULL; switch (flag) { case READ_LINE: while (GetConfigLineWrapper (Fvwm_fd, &buffer)) { cur_pos = buffer; skip_space (&cur_pos); if (!strncasecmp (Module, cur_pos, ModuleLen)) { retstring = cur_pos; cur_pos += ModuleLen; displaced = *cur_pos; if (displaced == '*') status = READ_OPTION; else if (displaced == '\0') status = READ_LINE; else if (iswhite (displaced)) status = READ_ARG; else status = READ_LINE; break; } } break; case READ_OPTION: *cur_pos = displaced; retstring = ++cur_pos; while (*cur_pos != '*' && !iswhite (*cur_pos)) cur_pos++; displaced = *cur_pos; *cur_pos = '\0'; if (displaced == '*') status = READ_OPTION; else if (displaced == '\0') status = READ_LINE; else if (iswhite (displaced)) status = READ_ARG; else status = READ_LINE; break; case READ_ARG: *cur_pos = displaced; skip_space (&cur_pos); retstring = cur_pos; while (!iswhite (*cur_pos)) cur_pos++; displaced = *cur_pos; *cur_pos = '\0'; if (displaced == '\0') status = READ_LINE; else if (iswhite (displaced)) status = READ_ARG; else status = READ_LINE; break; case READ_REST_OF_LINE: status = READ_LINE; *cur_pos = displaced; skip_space (&cur_pos); retstring = cur_pos; break; } if (retstring && retstring[0] == '\0') retstring = NULL; return retstring; } int OpenConsole() { #ifdef PRINT_CONSOLE if ((console=fopen("/dev/console","w"))==NULL) { fprintf(stderr,"%s: cannot open console\n",Module); return 0; } #endif return 1; } void ShutMeDown (int flag) { ConsoleDebug ("Bye Bye\n"); exit (flag); } void ConsoleMessage(char *fmt, ...) { #ifdef PRINT_CONSOLE va_list args; FILE *filep; if (console==NULL) filep=stderr; else filep=console; va_start(args,fmt); vfprintf(filep,fmt,args); va_end(args); #endif } #if defined(PRINT_DEBUG) || !defined(__GNUC__) void ConsoleDebug (char *fmt, ...) { #ifdef PRINT_CONSOLE #ifdef PRINT_DEBUG va_list args; FILE *filep; if (console==NULL) filep=stderr; else filep=console; va_start(args,fmt); vfprintf(filep,fmt,args); va_end(args); #endif #endif } #endif void DeadPipe (int nothing) { ConsoleDebug ("Bye Bye\n"); ShutMeDown (0); } void SendFvwmPipe (char *message,unsigned long window) { char *hold,*temp,*temp_msg; hold=message; while(1) { temp=strchr(hold,','); if (temp!=NULL) { temp_msg= (char *)safemalloc(temp-hold+1); strncpy(temp_msg,hold,(temp-hold)); temp_msg[(temp-hold)]='\0'; hold=temp+1; } else temp_msg=hold; SendText(Fvwm_fd, temp_msg, window); if(temp_msg!=hold) free(temp_msg); else break; } } static void main_loop (void) { fd_set readset; struct timeval tv; while(1) { FD_ZERO( &readset); FD_SET (Fvwm_fd[1],&readset); FD_SET (x_fd,&readset); tv.tv_sec=0; tv.tv_usec=0; if (!select(fd_width,&readset,NULL,NULL,&tv)) { FD_ZERO (&readset); FD_SET (Fvwm_fd[1],&readset); FD_SET (x_fd, &readset); select(fd_width,&readset,NULL,NULL,NULL); } if (FD_ISSET (x_fd, &readset) || XPending (theDisplay)) { xevent_loop(); } if (FD_ISSET(Fvwm_fd[1],&readset)) { ReadFvwmPipe(); } } } static int extract_int (char *p, int *n) { char *s; for (s = p; *s; s++) { if (*s < '0' || *s > '9') { return 0; } } *n = atoi (p); return 1; } char *copy_string (char **target, char *src) { int len = strlen (src); if (*target) Free (*target); *target = (char *)safemalloc ((len + 1) * sizeof (char)); strcpy (*target, src); return *target; } static char *conditional_copy_string (char **s1, char *s2) { if (*s1) return *s1; else return copy_string (s1, s2); } #if __GNUC__ > 2 #define SET_MANAGER(manager,field,value) \ do { \ int id = manager; \ if (id == -1) { \ for (id = 0; id < globals.num_managers; id++) { \ globals.managers[id].field = value; \ } \ } \ else if (id < globals.num_managers) { \ globals.managers[id].field = value; \ } \ else { \ ConsoleMessage ("Internal error in SET_MANAGER: %d\n", id); \ } \ } while (0) #else #define SET_MANAGER(manager,field,value) \ do { \ int id = manager; \ if (id == -1) { \ for (id = 0; id < globals.num_managers; id++) { \ globals.managers[id].##field = value; \ } \ } \ else if (id < globals.num_managers) { \ globals.managers[id].##field = value; \ } \ else { \ ConsoleMessage ("Internal error in SET_MANAGER: %d\n", id); \ } \ } while (0) #endif /* GCC 2 */ static void read_in_resources (char *file) { char *p, *q; int i, n, manager; char *option1; Resolution r; ButtonState state; if (!init_config_file (file)) return; while ((p = read_next_cmd (READ_LINE))) { ConsoleDebug ("line: %s\n", p); option1 = read_next_cmd (READ_OPTION); if (option1 == NULL) continue; ConsoleDebug ("option1: %s\n", option1); if (!strcasecmp (option1, "nummanagers")) { p = read_next_cmd (READ_ARG); if (!option1) { ConsoleMessage ("Error in input file\n"); continue; } if (extract_int (p, &n) == 0) { ConsoleMessage ("This is not a number: %s\n", p); continue; } if (n > 0) { allocate_managers (n); ConsoleDebug ("num managers: %d\n", n); } else { ConsoleMessage ("You can't have zero managers. I'll give you one.\n"); allocate_managers (1); } } else { /* these all can specify a specific manager */ if (globals.managers == NULL) { ConsoleDebug ("I'm assuming you only want one manager\n"); allocate_managers (1); } manager = 0; if (option1[0] >= '0' && option1[0] <= '9') { if (extract_int (option1, &manager) == 0 || manager <= 0 || manager > globals.num_managers) { ConsoleMessage ("This is not a valid manager: %s.\n", option1); manager = 0; } option1 = read_next_cmd (READ_OPTION); if (!option1) { ConsoleMessage ("Error in input file\n"); continue; } } manager--; /* -1 means global */ ConsoleDebug ("Applying %s to manager %d\n", option1, manager); if (!strcasecmp (option1, "resolution")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file\n"); continue; } ConsoleDebug ("resolution: %s\n", p); if (!strcasecmp (p, "global")) r = SHOW_GLOBAL; else if (!strcasecmp (p, "desk")) r = SHOW_DESKTOP; else if (!strcasecmp (p, "page")) r = SHOW_PAGE; SET_MANAGER (manager, res, r); } else if (!strcasecmp (option1, "font")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file\n"); continue; } ConsoleDebug ("font: %s\n", p); SET_MANAGER (manager, fontname, copy_string (&globals.managers[id].fontname, p)); } else if (!strcasecmp (option1, "geometry")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file\n"); continue; } SET_MANAGER (manager, geometry, copy_string (&globals.managers[id].geometry, p)); } else if (!strcasecmp (option1, "dontshow")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input_file\n"); continue; } do { ConsoleDebug ("dont show: %s\n", p); if (manager == -1) { int i; for (i = 0; i < globals.num_managers; i++) add_to_stringlist (&globals.managers[i].dontshow, p); } else { add_to_stringlist (&globals.managers[manager].dontshow, p); } p = read_next_cmd (READ_ARG); } while (p); } else if (!strcasecmp (option1, "show")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input_file\n"); continue; } do { ConsoleDebug ("show: %s\n", p); if (manager == -1) { int i; for (i = 0; i < globals.num_managers; i++) add_to_stringlist (&globals.managers[i].show, p); } else { add_to_stringlist (&globals.managers[manager].show, p); } p = read_next_cmd (READ_ARG); } while (p); } else if (!strcasecmp (option1, "background")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file\n"); continue; } ConsoleDebug ("default background: %s\n", p); for ( i = 0; i < NUM_CONTEXTS; i++ ) SET_MANAGER (manager, backColorName[i], conditional_copy_string (&globals.managers[id].backColorName[i], p)); } else if (!strcasecmp (option1, "foreground")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file\n"); continue; } ConsoleDebug ("default foreground: %s\n", p); for ( i = 0; i < NUM_CONTEXTS; i++ ) SET_MANAGER (manager, foreColorName[i], conditional_copy_string (&globals.managers[id].foreColorName[i], p)); } else if (!strcasecmp (option1, "action")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file: need arguments to action\n"); continue; } if (!strcasecmp (p, "click1")) { i = CLICK1; } else if (!strcasecmp (p, "click2")) { i = CLICK2; } else if (!strcasecmp (p, "click3")) { i = CLICK3; } else if (!strcasecmp (p, "select")) { i = SELECT; } else { ConsoleMessage ("Error in input file: this isn't a valid action name: %s\n", p); continue; } q = read_next_cmd (READ_REST_OF_LINE); if (!q) { ConsoleMessage ("Error in input file: need an action\n"); continue; } ConsoleDebug ("Setting action for %s: %s\n", actionNames[i], q); SET_MANAGER (manager, actions[i], copy_string (&globals.managers[id].actions[i], q)); } else if (!strcasecmp (option1, "showtitle")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file: need argument to showtitle\n"); continue; } if (!strcasecmp (p, "true")) { i = 1; } else if (!strcasecmp (p, "false")) { i = 0; } else { ConsoleMessage ("Error in input file. What is this: %s?\n", p); continue; } ConsoleDebug ("Setting showtitle to: %d\n", i); SET_MANAGER (manager, use_titlename, i); } else if (!strcasecmp (option1, "plainButton") || !strcasecmp (option1, "selectButton") || !strcasecmp (option1, "focusButton") || !strcasecmp (option1, "focusandselectButton")) { if ( !strcasecmp (option1, "plainButton") ) i = PLAIN_CONTEXT; else if ( !strcasecmp (option1, "selectButton") ) i = SELECT_CONTEXT; else if (!strcasecmp (option1, "focusandselectButton")) i = FOCUS_SELECT_CONTEXT; else i = FOCUS_CONTEXT; p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file: need argument to %s\n", option1); continue; } else if (!strcasecmp (p, "flat")) { state = BUTTON_FLAT; } else if (!strcasecmp (p, "up")) { state = BUTTON_UP; } else if (!strcasecmp (p, "down")) { state = BUTTON_DOWN; } else { ConsoleMessage ("Error in input file: this isn't a valid button state: %s\n", p); continue; } ConsoleDebug ("Setting buttonState[%s] to %s\n", contextDefaults[i].name, p); SET_MANAGER (manager, buttonState[i], state); /* check for optional fore color */ p = read_next_cmd (READ_ARG); if ( !p ) continue; ConsoleDebug ("Setting foreColorName[%s] to %s\n", contextDefaults[i].name, p); SET_MANAGER (manager, foreColorName[i], copy_string (&globals.managers[id].foreColorName[i], p)); /* check for optional back color */ p = read_next_cmd (READ_ARG); if ( !p ) continue; ConsoleDebug ("Setting backColorName[%s] to %s\n", contextDefaults[i].name, p); SET_MANAGER (manager, backColorName[i], copy_string (&globals.managers[id].backColorName[i], p)); } else if (!strcasecmp (option1, "followfocus")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file: need argument to followfocus\n"); continue; } if (!strcasecmp (p, "true")) { i = 1; } else if (!strcasecmp (p, "false")) { i = 0; } else { ConsoleMessage ("Error in input file. What is this: %s?\n", p); continue; } ConsoleDebug ("Setting followfocus to: %d\n", i); SET_MANAGER (manager, followFocus, i); } else if (!strcasecmp (option1, "sort")) { p = read_next_cmd (READ_ARG); if (!p) { ConsoleMessage ("Error in input file: need argument to sort\n"); continue; } if (!strcasecmp (p, "true")) { i = 1; } else if (!strcasecmp (p, "false")) { i = 0; } else { ConsoleMessage ("Error in input file. What is this: %s?\n", p); continue; } ConsoleDebug ("Setting sort to: %d\n", i); SET_MANAGER (manager, sort, i); } else { ConsoleMessage ("Unknown option: %s\n", p); } } } if (globals.managers == NULL) { ConsoleDebug ("I'm assuming you only want one manager\n"); allocate_managers (1); } print_managers(); close_config_file(); } int main (int argc, char **argv) { char *temp, *s; FvwmPacketBody temppacket; if ((char *)&temppacket.add_config_data.window_gravity - (char *)&temppacket != 21 * sizeof (long)) { fprintf (stderr, "Bad packet structure. Can't run. Sorry\n"); exit (1); } OpenConsole(); init_globals(); init_winlists(); temp = argv[0]; s = strrchr (argv[0], '/'); if (s != NULL) temp = s + 1; if((argc != 6) && (argc != 7)) { fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",Module, VERSION); ShutMeDown (1); } Fvwm_fd[0] = atoi(argv[1]); Fvwm_fd[1] = atoi(argv[2]); init_display(); init_boxes(); signal (SIGPIPE, DeadPipe); read_in_resources (argv[3]); assert (globals.managers); fd_width = sysconf(_SC_OPEN_MAX); SetMessageMask(Fvwm_fd,M_CONFIGURE_WINDOW | M_RES_CLASS | M_RES_NAME | M_ADD_WINDOW | M_DESTROY_WINDOW | M_ICON_NAME | M_DEICONIFY | M_ICONIFY | M_END_WINDOWLIST | M_NEW_DESK | M_NEW_PAGE | M_FOCUS_CHANGE | M_WINDOW_NAME); SendInfo (Fvwm_fd, "Send_WindowList", 0); main_loop(); ConsoleMessage ("Shouldn't be here\n"); return 0; }