Logo Search packages:      
Sourcecode: joe version File versions  Download package

help.c

/*
 *    Help system
 *    Copyright
 *          (C) 1992 Joseph H. Allen
 *          (C) 2001 Marek 'Marx' Grac
 *
 *    This file is part of JOE (Joe's Own Editor)
 */
#include "types.h"

struct help {
      unsigned char     *text;            /* help text with attributes */
      unsigned int      lines;            /* number of lines */
      struct help *prev;            /* previous help screen */
      struct help *next;            /* nex help screen */
      unsigned char     *name;            /* context name for context sensitive help */
};

#define NOT_ENOUGH_MEMORY -11

int bg_help;      /* Background color for help */

struct help *help_actual = NULL;    /* actual help screen */
struct help *help_ptr = NULL;       /* build pointer */

/* 
 * Process help file
 * Returns new line number
 */

int help_init(JFILE *fd,unsigned char *bf,int line)
{
      unsigned char buf[1024];                  /* input buffer */

      struct help *tmp;
      unsigned int bfl;                   /* buffer length */
      unsigned int hlpsiz, hlpbsz;              /* number of used/allocated bytes for tmp->text */
      unsigned char *tempbuf;

      if (bf[0] == '{') {                 /* start of help screen */
            tmp = (struct help *) joe_malloc(sizeof(struct help));

            tmp->text = NULL;
            tmp->lines = 0;
            hlpsiz = 0;
            hlpbsz = 0;
            tmp->name = vsncpy(NULL, 0, sz(bf + 1) - 1); /* -1 kill the \n */

            while ((jfgets(buf, sizeof(buf), fd)) && (buf[0] != '}')) {
                  ++line;
                  bfl = zlen(buf);
                  if (hlpsiz + bfl > hlpbsz) {
                        if (tmp->text) {
                              tempbuf = (unsigned char *) joe_realloc(tmp->text, hlpbsz + bfl + 1024);
                              tmp->text = tempbuf;
                        } else {
                              tmp->text = (unsigned char *) joe_malloc(bfl + 1024);
                              tmp->text[0] = 0;
                        }
                        hlpbsz += bfl + 1024;
                  }
                  zcpy(tmp->text + hlpsiz, buf);
                  hlpsiz += bfl;
                  ++tmp->lines;
            }
            tmp->prev = help_ptr;
            tmp->next = NULL;
            if (help_ptr) {
                  help_ptr->next = tmp;
            } else {
                  help_actual = tmp;
            }
            help_ptr = tmp;
            if (buf[0] == '}') {          /* set new help screen as actual one */
                  ++line;
            } else {
                  fprintf(stderr, (char *)joe_gettext(_("\n%d: EOF before end of help text\n")),line);
            }
      }
      return line;
}

/*
 * Find context help - find help entry with the same name
 */

struct help *find_context_help(unsigned char *name)
{
      struct help *tmp = help_actual;

      while (tmp->prev != NULL)     /* find the first help entry */
            tmp = tmp->prev;

      while (tmp != NULL && zcmp(tmp->name, name) != 0)
            tmp = tmp->next;

      return tmp;
}

int help_is_utf8;

/*
 * Display help text
 */
void help_display(Screen *t)
{
      unsigned char *str;
      int y, x, c, z;
      int atr = BG_COLOR(bg_help);

      if (help_actual) {
            str = help_actual->text;
      } else {
            str = NULL;
      }

      for (y = skiptop; y != t->wind; ++y) {
            if (t->t->updtab[y]) {
                  unsigned char *start = str, *eol;
                  int width=0;
                  int nspans=0;
                  int spanwidth;
                  int spancount=0;
                  int spanextra;
                  int len;

                  eol = zchr(str, '\n');

                  /* First pass: count no. springs \| and determine minimum width */
                  while(*str && *str!='\n') {
                        if (*str == '\\') {
                              ++str;
                              switch(*str) {
                                    case 'i':
                                    case 'I':
                                    case 'u':
                                    case 'U':
                                    case 'd':
                                    case 'D':
                                    case 'b':
                                    case 'B':
                                    case 'f':
                                    case 'F':
                                          ++str;
                                          break;
                                    case '|':
                                          ++str;
                                          ++nspans;
                                          break;
                                    case 0:
                                          break;
                                    default:
                                          ++str;
                                          ++width;
                              }
                        } else {
                              len = eol - str;
                              if (help_is_utf8)
                                    c = utf8_decode_fwrd(&str, &len);
                              else {
                                    c = *str++;
                                    --len;
                              }
                              width += joe_wcwidth(!!locale_map->type, c);
                        }
                  }
                  str = start;
                  /* Now calculate span width */
                  if (width >= t->w - 1 || nspans==0) {
                        spanwidth = 0;
                        spanextra = nspans;
                  } else {
                        spanwidth = ((t->w - 1) - width)/nspans;
                        spanextra = nspans - ((t->w - 1) - width - nspans*spanwidth);
                  }
                  /* Second pass: display text */
                  for (x = 0; x != t->w - 1; ++x) {
                        if (*str == '\n' || !*str) {
                              if (eraeol(t->t, x, y, BG_COLOR(bg_help))) {
                                    return;
                              } else {
                                    break;
                              }
                        } else {
                              if (*str == '\\') {
                                    switch (*++str) {
                                    case '|':
                                          ++str;
                                          for (z=0;z!=spanwidth;++z)
                                                outatr(locale_map,t->t,t->t->scrn+x+y*t->w+z,t->t->attr+x+y*t->w+z,x+z,y,' ',atr);
                                          if (spancount++ >= spanextra) {
                                                outatr(locale_map,t->t,t->t->scrn+x+y*t->w+z,t->t->attr+x+y*t->w+z,x+z,y,' ',atr);
                                                ++z;
                                          }
                                          x += z-1;
                                          continue;
                                    case 'i':
                                    case 'I':
                                          atr ^= INVERSE;
                                          ++str;
                                          --x;
                                          continue;
                                    case 'u':
                                    case 'U':
                                          atr ^= UNDERLINE;
                                          ++str;
                                          --x;
                                          continue;
                                    case 'd':
                                    case 'D':
                                          atr ^= DIM;
                                          ++str;
                                          --x;
                                          continue;
                                    case 'b':
                                    case 'B':
                                          atr ^= BOLD;
                                          ++str;
                                          --x;
                                          continue;
                                    case 'f':
                                    case 'F':
                                          atr ^= BLINK;
                                          ++str;
                                          --x;
                                          continue;
                                    case 0:     
                                          --x;
                                          continue;
                                    }
                              }
                              len = eol - str;
                              if (help_is_utf8)
                                    c = utf8_decode_fwrd(&str, &len);
                              else {
                                    c = *str++;
                                    --len;
                              }

                              outatr(locale_map,
                                     t->t, t->t->scrn + x + y * t->w, 
                                           t->t->attr + x + y * t->w, x, y,
                                     c, atr);
                              x += (joe_wcwidth(!!locale_map->type, c) - 1);
                        }
                  }
                  atr = BG_COLOR(bg_help);
                  t->t->updtab[y] = 0;
            }

            while (*str && *str != '\n')
                  ++str;
            if (*str == '\n')
                  ++str;
      }
}

/*
 * Show help screen 
 */
int help_on(Screen *t)
{
      if (help_actual) {
            t->wind = help_actual->lines + skiptop;
            if ((t->h - t->wind) < FITHEIGHT) {
                  t->wind = t->h - FITHEIGHT;
            }
            if (t->wind < 0) {
                  t->wind = skiptop;
                  return -1;
            }
            wfit(t);
            msetI(t->t->updtab + skiptop, 1, t->wind);
            return 0;
      } else {
            return -1;
      }
}

/*
 * Hide help screen
 */
static void help_off(Screen *t)
{
      t->wind = skiptop;
      wfit(t);
}

/*
 * Show/hide current help screen
 */
int u_help(BASE *base)
{
      W *w = base->parent;
      struct help *new_help;

      if (w->huh && (new_help = find_context_help(w->huh)) != NULL) {
            if (help_actual != new_help) {
                  if (w->t->wind != skiptop)
                        help_off(w->t);
                  help_actual = new_help;       /* prepare context help */
            }
      }
      if (w->t->wind == skiptop) {
            return help_on(w->t);               /* help screen is hidden, so show the actual one */
      } else {
            help_off(w->t);                     /* hide actual help screen */
            return 0;
      }
}

/*
 * Show next help screen (if it is possible)
 */
int u_help_next(BASE *base)
{
      W *w = base->parent;

      if (help_actual && help_actual->next) {         /* is there any next help screen? */
            if (w->t->wind != skiptop) {
                  help_off(w->t);               /* if help screen was visible, then hide it */
            }
            help_actual = help_actual->next;    /* change to next help screen */
            return help_on(w->t);               /* show actual help screen */
      } else {
            return -1;
      }
}

/*
 * Show previous help screen (if it is possible)
 */
int u_help_prev(BASE *base)
{
      W *w = base->parent;

      if (help_actual && help_actual->prev) {         /* is there any previous help screen? */
            if (w->t->wind != skiptop)
                  help_off(w->t);               /* if help screen was visible, then hide it */
            help_actual = help_actual->prev;    /* change to previous help screen */
            return help_on(w->t);               /* show actual help screen */
      } else {
            return -1;
      }
}

Generated by  Doxygen 1.6.0   Back to index