Logo Search packages:      
Sourcecode: vile version File versions

menu.c

/************************************************************************/
/*  File        : menu.c                                                */
/*  Description : Implement a Motif MenuBar into Mxvile                 */
/*                Parse a File (environment variable XVILE_MENU)        */
/*                and create it at the top of the window                */
/*  Auteur      : Philippe CHASSANY                                     */
/*  Date        : 20/02/97                                              */
/************************************************************************/

/*
 * $Header: /usr/build/vile/vile/RCS/menu.c,v 1.42 2002/01/22 00:12:34 tom Exp $
 */

/* Vile includes */
#include "estruct.h"
#include "edef.h"

#if SYS_VMS
#include <processes.h>
#define fork vfork
#define Token MenuTokens
#endif

/* Tokens of the rc file */
#define MAX_TOKEN   200
struct _tok_ {
    char type;
    int idx_cascade;
    char label[NSTRING];
    char action[NSTRING];
    int macro;
} Token[MAX_TOKEN];
static int Nb_Token = 0;

/* Actions of the rc file */

typedef struct {
    char name[30];
    const ActionFunc fact;
} TAct;

/* Common Actions = User defined Actions */
/* Why not use dynamic link library to get functions ? */
static void common_action(char *action);
static TAct Actions[] =
{
    {"nop", 0},
    {"new_xvile", common_action},
    {"edit_rc", common_action},
    {"parse_rc", common_action},
    {"edit_mrc", common_action},
};

static char *
menu_filename(void)
{
    char *result = cfg_locate(menu_file, LOCATE_SOURCE);
#if SYS_UNIX
    /* just for backward compatibility */
    if (result == 0 && strcmp(menu_file, ".vilemenu")) {
      result = cfg_locate(".vilemenu", LOCATE_SOURCE);
    }
#endif
    return result;
}

static char *
startup_filename(void)
{
    return cfg_locate(startup_file, LOCATE_SOURCE);
}

static void
edit_file(char *fname)
{
    if (fname != 0 && *fname != EOS && ffexists(fname)) {
      splitwind(FALSE, 1);
      getfile(fname, TRUE);
    } else
      no_file_found();
}

/************************************************************************/
/* All the common actions are handled by this function                  */
/************************************************************************/
static void
common_action(char *action)
{
    TRACE(("Action=%s\n", action));

    if (!strcmp(action, "new_xvile")) {
      int pid;
      int status;
      char path[NFILEN];

      pathcat(path, exec_pathname, prog_arg);

      if ((pid = fork()) > 0) {
          while (wait(&status) >= 0)
            /* */ ;
      } else if (pid == 0) {
          if ((pid = fork()) > 0) {
            _exit(0);   /* abandon exec'ing process */
          } else if (pid == 0) {
            newprocessgroup(FALSE, 1);
            execl(path, "xvile", "-display", x_get_display_name(), NULL, 0);
            _exit(errno);     /* just in case exec-failed */
          }
      }
    } else if (!strcmp(action, "edit_rc")) {
      edit_file(startup_filename());
    } else if (!strcmp(action, "parse_rc")) {
      dofile(startup_filename());
    } else if (!strcmp(action, "edit_mrc")) {
      edit_file(menu_filename());
    }
}

/************************************************************************/
/* Test if the action name is part of the Actions of the rc file        */
/************************************************************************/
static int
is_action(char *action)
{
    unsigned i;

    for (i = 0; i < TABLESIZE(Actions); i++) {
      if (!strcmp(Actions[i].name, action))
          return 1;
    }

    return 0;
}

/************************************************************************/
/* Return the function pointer associated with the action name          */
/************************************************************************/
ActionFunc
vlmenu_action_func(char *action)
{
    unsigned i;

    for (i = 0; i < TABLESIZE(Actions); i++) {
      if (!strcmp(Actions[i].name, action))
          return Actions[i].fact;
    }

    return 0;
}

/************************************************************************/
/* Test if the action name is a bind (inspired from vile sources        */
/************************************************************************/
int
vlmenu_is_bind(char *action)
{
    static TBUFF *tok;

    (void) get_token(action, &tok, EOS, (int *) 0);
    if (tb_length(tok) != 0
      && engl2fnc(tb_values(tok)) != NULL)
      return 1;

    return 0;
}

/************************************************************************/
/* Test if the action name begins with the keyword "cmd",               */
/************************************************************************/
char *
vlmenu_is_cmd(char *action)
{
    static TBUFF *tok;
    char *result = (char *) get_token(action, &tok, EOS, (int *) 0);

    if (tb_length(tok) != 0
      && !strcmp(tb_values(tok), "cmd"))
      return result;

    return 0;
}

/************************************************************************/
/* Main function to parse the rc file                                   */
/************************************************************************/
int
parse_menu(const char *rc_filename)
{
    FILE *fp;
    char line[1000];
    char *ptr_tok;
    int n, tmp;
    int cascade_token = 0;
    int nlig = 0;

    TRACE(("parse_menu(%s)\n", rc_filename));

    if ((fp = fopen(rc_filename, "r")) == NULL)
      return FALSE;

    Nb_Token = 0;
    while (fgets(line, sizeof(line), fp) != NULL && Nb_Token < MAX_TOKEN - 2) {
      nlig++;

      /* Let a tab begin inline comment */
      if ((ptr_tok = strchr(line, '\t')) != 0)
          *ptr_tok = EOS;

      ptr_tok = strtok(line, ":");
      if (ptr_tok == NULL)
          continue;

      switch (*ptr_tok) {
      case ';':         /* FALLTHRU */
      case '"':
      case '#':
          continue;

      case 'C':
          Token[Nb_Token].type = *ptr_tok;
          if ((ptr_tok = strtok(NULL, ":\n")) != NULL) {
            strcpy(Token[Nb_Token].label, ptr_tok);
            cascade_token = Nb_Token;
            if ((ptr_tok = strtok(NULL, ":\n")) != NULL) {
                Token[Nb_Token].type = 'H';
            }
            Nb_Token++;
          } else {
            fclose(fp);
            return FALSE;
          }
          break;

      case 'S':
          Token[Nb_Token].type = *ptr_tok;
          Token[Nb_Token].idx_cascade = cascade_token;
          Nb_Token++;
          break;

      case 'L':
          Token[Nb_Token].type = 'S';
          Token[Nb_Token].idx_cascade = cascade_token;
          Nb_Token++;
          Token[Nb_Token].type = *ptr_tok;
          Token[Nb_Token].idx_cascade = cascade_token;
          if ((ptr_tok = strtok(NULL, ":\n")) != NULL) {
            strcpy(Token[Nb_Token].action, ptr_tok);
            cascade_token = Nb_Token;
          }
          Nb_Token++;
          break;

      case 'B':
          Token[Nb_Token].type = *ptr_tok;
          Token[Nb_Token].idx_cascade = cascade_token;
          n = 0;
          while ((ptr_tok = strtok(NULL, ":\n")) != NULL) {
            switch (n) {
            case 0:
                strcpy(Token[Nb_Token].label, ptr_tok);
                break;
            case 1:
                if (isDigit((int) *ptr_tok)) {
                  tmp = (int) atoi(ptr_tok);
                  Token[Nb_Token].macro = tmp;
                } else {
                  if (is_action(ptr_tok)
                      || vlmenu_is_bind(ptr_tok)
                      || vlmenu_is_cmd(ptr_tok)) {
                      strcpy(Token[Nb_Token].action, ptr_tok);
                  } else {
                      printf("Error in line %d : '%s' is not an action\n",
                           nlig, ptr_tok);
                      strcpy(Token[Nb_Token].action, "beep");
                  }
                }
                break;
            }
            n++;
          }
          if (n != 2) {
            fclose(fp);
            return FALSE;
          }
          Nb_Token++;
          break;
      }
    }
    fclose(fp);

    return TRUE;
}

/************************************************************************/
/* Debug function to print the  tokens of the rc file                   */
/************************************************************************/
#if OPT_TRACE
static void
print_token(void)
{
    int i;

    for (i = 0; i < Nb_Token; i++) {
      switch (Token[i].type) {
      case 'C':
      case 'H':
          Trace("%c %s\n",
              Token[i].type,
              Token[i].label);
          break;
      case 'S':
          Trace("\t%c (%s)\n",
              Token[i].type,
              Token[Token[i].idx_cascade].label);
          break;
      case 'L':
          Trace("\t%c %s\n",
              Token[i].type,
              Token[i].action);
          break;
      case 'B':
          if (Token[i].macro > 0)
            Trace("\t%c %s(%s) -> Macro-%d\n",
                  Token[i].type,
                  Token[i].label,
                  Token[Token[i].idx_cascade].label,
                  Token[i].macro);
          else
            Trace("\t%c %s(%s) -> Action-%s\n",
                  Token[i].type,
                  Token[i].label,
                  Token[Token[i].idx_cascade].label,
                  Token[i].action);
      }
    }
}
#endif

/************************************************************************/
/* Main function : Take the menu-bar as argument and create all the     */
/* Cascades, PullDowns Menus and Buttons read from the rc file          */
/************************************************************************/
int
do_menu(void *menub)
{
    int i;
    char *accel, *macro;
    void *pm = 0;
    void *pm_w;
    int rc;
    char *menurc = menu_filename();

    if (menurc == 0) {
      mlforce("No menu-file found");
      return FALSE;
    }
    if ((rc = parse_menu(menurc)) != TRUE) {
      mlforce("Error parsing menu-file");
      return FALSE;
    }
#if OPT_TRACE
    print_token();
#endif

    for (i = 0; i < Nb_Token; i++) {
      switch (Token[i].type) {
          /* HELP CASCADE */
      case 'C':
      case 'H':
          pm = gui_make_menu(menub, Token[i].label, Token[i].type);
          break;

          /* SEPARATOR WIDGET */
      case 'S':
          gui_add_menu_item(pm, "sep", NULL, Token[i].type);
          break;

          /* LIST (BUFFER LIST) */
      case 'L':
          if (!strcmp(Token[i].action, "list_buff")) {
            gui_add_list_callback(pm);
          }
          break;

          /* BUTTON WIDGET */
      case 'B':
          if (Token[i].macro > 0) {
            macro = castalloc(char, 50);
            sprintf(macro, "execute-macro-%d", Token[i].macro);
            accel = give_accelerator(macro);
            pm_w = gui_add_menu_item(pm, Token[i].label, accel,
                               Token[i].type);

            gui_add_func_callback(pm_w, macro);
          } else {
            accel = give_accelerator(Token[i].action);
            pm_w = gui_add_menu_item(pm, Token[i].label, accel,
                               Token[i].type);
            gui_add_func_callback(pm_w, Token[i].action);
          }
          break;
      }
    }
    return TRUE;
}

/************************************************************************/

int
vlmenu_load(int f, int n)
{
    if (gui_create_menus()) {
      return gui_show_menus(f, n);
    }
    return FALSE;
}

Generated by  Doxygen 1.6.0   Back to index