Example #1
0
Point
line_end_position (int count)
{
  Point pt = line_beginning_position (count);
  pt.o = astr_len (get_line_text (pt.p));
  return pt;
}
Example #2
0
static int
find_substr (astr as, const char *s2, size_t s2size, size_t from, size_t to,
             bool forward, bool notbol, bool noteol, bool regex, bool icase)
{
  int ret = -1;
  struct re_pattern_buffer pattern;
  struct re_registers search_regs;
  reg_syntax_t syntax = RE_SYNTAX_EMACS;

  memset (&pattern, 0, sizeof (pattern));

  if (!regex)
    syntax |= RE_PLAIN;
  if (icase)
    syntax |= RE_ICASE;
  re_set_syntax (syntax);
  search_regs.num_regs = 1;

  re_find_err = re_compile_pattern (s2, (int) s2size, &pattern);
  pattern.not_bol = notbol;
  pattern.not_eol = noteol;
  if (!re_find_err)
    ret = re_search (&pattern, astr_cstr (as), (int) astr_len (as), forward ? from : to - 1,
                     forward ? (to - from) : -(to - 1 - from), &search_regs);

  if (ret >= 0)
    {
      ret = forward ? search_regs.end[0] : ret;
      free (search_regs.start);
      free (search_regs.end);
    }

  regfree (&pattern);
  return ret;
}
Example #3
0
static bool
search (Point pt, const char *s, int forward, int regexp)
{
  Line *lp = pt.p;
  astr as = get_line_text (lp);
  size_t ssize = strlen (s), from = 0, to = astr_len (as);
  bool downcase = get_variable_bool ("case-fold-search") && no_upper (s, ssize, regexp);
  bool notbol = false, noteol = false;
  int pos;

  if (ssize < 1)
    return false;

  /* Match first line. */
  if (forward)
    {
      notbol = pt.o > from;
      from = pt.o;
    }
  else
    {
      noteol = pt.o < to;
      to = pt.o;
    }
  pos = find_substr (as, s, ssize, from, to, forward, notbol, noteol, regexp, downcase);

  /* Match following lines. */
  while (pos < 0)
    {
      lp = (forward ? get_line_next : get_line_prev) (lp);
      if (lp == get_buffer_lines (cur_bp))
        break;
      as = get_line_text (lp);
      pos = find_substr (as, s, ssize, 0, astr_len (as), forward, false, false, regexp, downcase);
    }

  if (pos < 0)
    return false;

  while (get_buffer_pt (cur_bp).p != lp)
    (forward ? next_line : previous_line) ();
  pt = get_buffer_pt (cur_bp);
  pt.o = pos;
  set_buffer_pt (cur_bp, pt);
  thisflag |= FLAG_NEED_RESYNC;
  return true;
}
Example #4
0
Point point_max(void)
{
  Point pt;
  pt.p = list_prev(cur_bp->lines);
  pt.n = cur_bp->num_lines;
  pt.o = astr_len(list_prev(cur_bp->lines)->item);
  return pt;
}
Example #5
0
Point
point_max (void)
{
  Point pt;
  pt.p = get_line_prev (get_buffer_lines (cur_bp));
  pt.n = get_buffer_last_line (cur_bp);
  pt.o = astr_len (get_line_text (get_line_prev (get_buffer_lines (cur_bp))));
  return pt;
}
Example #6
0
static void draw_line(size_t line, size_t startcol, Window *wp, Line *lp,
		      size_t lineno, Region *r, int highlight)
{
  size_t x, i;

  term_move(line, 0);
  for (x = 0, i = startcol; i < astr_len(lp->item) && x < wp->ewidth; i++) {
    if (highlight && in_region(lineno, i, r))
      outch(*astr_char(lp->item, (ptrdiff_t)i), FONT_REVERSE, &x);
    else
      outch(*astr_char(lp->item, (ptrdiff_t)i), FONT_NORMAL, &x);
  }

  draw_end_of_line(line, wp, lineno, r, highlight, x, i);
}
Example #7
0
int point_dist(Point pt1, Point pt2)
{
  int size = 0;
  Line *lp;

  if (cmp_point(pt1, pt2) > 0)
    swap_point(&pt1, &pt2);

  for (lp = pt1.p; ; lp = list_next(lp)) {
    size += astr_len(lp->item);

    if (lp == pt1.p)
      size -= pt1.o;

    if (lp == pt2.p) {
      size -= astr_len(lp->item) - pt2.o;
      break;
    }
    else
      size++;
  }

  return size;
}
Example #8
0
static void draw_status_line(size_t line, Window *wp)
{
  size_t i;
  char *buf, *eol_type;
  Point pt = window_pt(wp);
  astr as, bs;

  term_attrset(1, FONT_REVERSE);

  term_move(line, 0);
  for (i = 0; i < wp->ewidth; ++i)
    term_addch('-');

  if (cur_bp->eol == coding_eol_cr)
    eol_type = "(Mac)";
  else if (cur_bp->eol == coding_eol_crlf)
    eol_type = "(DOS)";
  else
    eol_type = ":";
    
  term_move(line, 0);
  bs = astr_afmt(astr_new(), "(%d,%d)", pt.n+1, get_goalc_wp(wp));
  as = astr_afmt(astr_new(), "--%s%2s  %-15s   %s %-9s (Text",
                 eol_type, make_mode_line_flags(wp), wp->bp->name,
                 make_screen_pos(wp, &buf), astr_cstr(bs));
  free(buf);
  astr_delete(bs);

  if (wp->bp->flags & BFLAG_AUTOFILL)
    astr_cat_cstr(as, " Fill");
  if (wp->bp->flags & BFLAG_OVERWRITE)
    astr_cat_cstr(as, " Ovwrt");
  if (thisflag & FLAG_DEFINING_MACRO)
    astr_cat_cstr(as, " Def");
  if (wp->bp->flags & BFLAG_ISEARCH)
    astr_cat_cstr(as, " Isearch");

  astr_cat_char(as, ')');
  term_addnstr(astr_cstr(as), min(term_width(), astr_len(as)));
  astr_delete(as);

  term_attrset(1, FONT_NORMAL);
}
Example #9
0
/* set up the appropriate watch on the directory indicated by sfilename */
static int setup_inotify_watch(int notify_fd, struct astr *sfilename) {
	char dirbuf[astr_len(sfilename) + 1];
	char *dir;
	int dwatch;

	strcpy(dirbuf, astr_cstr(sfilename));
	dir = dirname(dirbuf);
	
	dwatch = inotify_add_watch(notify_fd, dir,
	                           IN_CLOSE_WRITE|IN_MOVED_TO);
	if(dwatch <= 0) {
		fprintf(stderr,
		        ERRORTEXT("Fatal: failed to add inotify watch for %s")
		        ": %s\n", dir, strerror(errno));
		exit(EXIT_FAILURE);
	}

	return dwatch;
}
Example #10
0
File: glue.c Project: gpaquet/zile
/*
 * Copy a region of text into an allocated buffer.
 */
char *
copy_text_block (size_t startn, size_t starto, size_t size)
{
  char *buf, *dp;
  size_t max_size, n, i;
  Line *lp;

  max_size = 10;
  dp = buf = (char *) xzalloc (max_size);

  lp = cur_bp->pt.p;
  n = cur_bp->pt.n;
  if (n > startn)
    do
      lp = lp->prev;
    while (--n > startn);
  else if (n < startn)
    do
      lp = lp->next;
    while (++n < startn);

  for (i = starto; dp - buf < (int) size;)
    {
      if (dp >= buf + max_size)
	{
	  int save_off = dp - buf;
	  max_size += 10;
	  buf = (char *) xrealloc (buf, max_size);
	  dp = buf + save_off;
	}
      if (i < astr_len (lp->text))
	*dp++ = *astr_char (lp->text, (ptrdiff_t) (i++));
      else
	{
	  *dp++ = '\n';
	  lp = lp->next;
	  i = 0;
	}
    }

  return buf;
}
Example #11
0
/*
 * Return the current directory.
 */
static astr get_current_dir(void)
{
  astr buf;
  int p;

  if (cur_bp->filename != NULL)
    /* If the current buffer has a filename, get the current directory
       name from it. */
    buf = astr_new_cstr(cur_bp->filename);
  else { /* Get the current directory name from the system. */
    buf = agetcwd();
    if (astr_len(buf) != 0 && *astr_char(buf, -1) != '/')
      astr_cat_char(buf, '/');
  }

  p = astr_rfind_cstr(buf, "/");
  astr_truncate(buf, p + 1);

  return buf;
}
Example #12
0
File: file.c Project: M1lan/zile
/*
 * Return a `~/foo' like path if the user is under his home directory,
 * else the unmodified path.
 */
astr
compact_path (astr path)
{
  struct passwd *pw = getpwuid (getuid ());

  if (pw != NULL)
    {
      /* Replace `/userhome/' (if found) with `~/'. */
      size_t homelen = strlen (pw->pw_dir);
      if (homelen > 0 && pw->pw_dir[homelen - 1] == '/')
        homelen--;

      if (astr_len (path) > homelen &&
          !strncmp (pw->pw_dir, astr_cstr (path), homelen) &&
          astr_get (path, homelen) == '/')
        astr_cpy (path, astr_cat_cstr (astr_new_cstr ("~/"),
                                       astr_cstr (path) + homelen + 1));
    }

  return path;
}
Example #13
0
static int kill_line(int literally)
{
  if (!eolp()) {
    if (warn_if_readonly_buffer())
      return FALSE;

    undo_save(UNDO_INSERT_BLOCK, cur_bp->pt,
              astr_len(cur_bp->pt.p->item) - cur_bp->pt.o, 0);
    undo_nosave = TRUE;
    while (!eolp()) {
      kill_ring_push(following_char());
      FUNCALL(delete_char);
    }
    undo_nosave = FALSE;

    thisflag |= FLAG_DONE_KILL;

    if (!literally)
      return TRUE;
  }

  if (list_next(cur_bp->pt.p) != cur_bp->lines) {
    if (!FUNCALL(delete_char))
      return FALSE;

    kill_ring_push('\n');

    thisflag |= FLAG_DONE_KILL;

    return TRUE;
  }

  minibuf_error("End of buffer");

  return FALSE;
}
Example #14
0
Point line_end_position(int count)
{
  Point pt = line_beginning_position(count);
  pt.o = astr_len(pt.p->item);
  return pt;
}
Example #15
0
File: file.c Project: M1lan/zile
/*
 * This functions does some corrections and expansions to
 * the passed path:
 *
 * - expands `~/' and `~name/' expressions;
 * - replaces `//' with `/' (restarting from the root directory);
 * - removes `..' and `.' entries.
 *
 * The return value indicates success or failure.
 */
bool
expand_path (astr path)
{
  int ok = true;
  const char *sp = astr_cstr (path);
  astr epath = astr_new ();

  if (*sp != '/' && *sp != '~')
    {
      astr_cat (epath, agetcwd ());
      if (astr_len (epath) == 0 ||
          astr_get (epath, astr_len (epath) - 1) != '/')
        astr_cat_char (epath, '/');
    }

  for (const char *p = sp; *p != '\0';)
    {
      if (*p == '/')
        {
          if (*++p == '/')
            { /* Got `//'.  Restart from this point. */
              while (*p == '/')
                p++;
              astr_truncate (epath, 0);
            }
          if (astr_len (epath) == 0 ||
              astr_get (epath, astr_len (epath) - 1) != '/')
            astr_cat_char (epath, '/');
        }
      else if (*p == '~' && (p == sp || p[-1] == '/'))
        { /* Got `/~' or leading `~'.  Restart from this point. */
          struct passwd *pw;

          astr_truncate (epath, 0);
          ++p;

          if (*p == '/')
            { /* Got `~/'.  Insert the user's home directory. */
              pw = getpwuid (getuid ());
              if (pw == NULL)
                {
                  ok = false;
                  break;
                }
              if (!STREQ (pw->pw_dir, "/"))
                astr_cat_cstr (epath, pw->pw_dir);
            }
          else
            { /* Got `~something'.  Insert that user's home directory. */
              astr as = astr_new ();
              while (*p != '\0' && *p != '/')
                astr_cat_char (as, *p++);
              pw = getpwnam (astr_cstr (as));
              if (pw == NULL)
                {
                  ok = false;
                  break;
                }
              astr_cat_cstr (epath, pw->pw_dir);
            }
        }
      else if (*p == '.' && (p[1] == '/' || p[1] == '\0'))
        { /* Got `.'. */
          ++p;
        }
      else if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0'))
        { /* Got `..'. */
          if (astr_len (epath) >= 1 && astr_get (epath, astr_len (epath) - 1) == '/')
            astr_truncate (epath, astr_len (epath) - 1);
          while (astr_get (epath, astr_len (epath) - 1) != '/' && astr_len (epath) >= 1)
            astr_truncate (epath, astr_len (epath) - 1);
          p += 2;
        }

      if (*p != '~')
        while (*p != '\0' && *p != '/')
          astr_cat_char (epath, *p++);
    }

  astr_cpy (path, epath);

  return ok;
}
Example #16
0
static astr
do_minibuf_read (const char *prompt, const char *value, size_t pos,
               Completion * cp, History * hp)
{
  static int overwrite_mode = 0;
  int c, thistab, lasttab = -1;
  size_t prompt_len;
  char *s;
  astr as = astr_new_cstr (value), saved = NULL;

  prompt_len = strlen (prompt);
  if (pos == SIZE_MAX)
    pos = astr_len (as);

  for (;;)
    {
      switch (lasttab)
        {
        case COMPLETION_MATCHEDNONUNIQUE:
          s = " [Complete, but not unique]";
          break;
        case COMPLETION_NOTMATCHED:
          s = " [No match]";
          break;
        case COMPLETION_MATCHED:
          s = " [Sole completion]";
          break;
        default:
          s = "";
        }
      draw_minibuf_read (prompt, astr_cstr (as), prompt_len, s, pos);

      thistab = -1;

      switch (c = getkey ())
        {
        case KBD_NOKEY:
          break;
        case KBD_CTRL | 'z':
          FUNCALL (suspend_emacs);
          break;
        case KBD_RET:
          term_move (term_height () - 1, 0);
          term_clrtoeol ();
          if (saved)
            astr_delete (saved);
          return as;
        case KBD_CANCEL:
          term_move (term_height () - 1, 0);
          term_clrtoeol ();
          if (saved)
            astr_delete (saved);
          astr_delete (as);
          return NULL;
        case KBD_CTRL | 'a':
        case KBD_HOME:
          pos = 0;
          break;
        case KBD_CTRL | 'e':
        case KBD_END:
          pos = astr_len (as);
          break;
        case KBD_CTRL | 'b':
        case KBD_LEFT:
          if (pos > 0)
            --pos;
          else
            ding ();
          break;
        case KBD_CTRL | 'f':
        case KBD_RIGHT:
          if (pos < astr_len (as))
            ++pos;
          else
            ding ();
          break;
        case KBD_CTRL | 'k':
          /* FIXME: do kill-register save. */
          if (pos < astr_len (as))
            astr_truncate (as, pos);
          else
            ding ();
          break;
        case KBD_BS:
          if (pos > 0)
            astr_remove (as, --pos, 1);
          else
            ding ();
          break;
        case KBD_CTRL | 'd':
        case KBD_DEL:
          if (pos < astr_len (as))
            astr_remove (as, pos, 1);
          else
            ding ();
          break;
        case KBD_INS:
          overwrite_mode = overwrite_mode ? 0 : 1;
          break;
        case KBD_META | 'v':
        case KBD_PGUP:
          if (cp == NULL)
            {
              ding ();
              break;
            }

          if (get_completion_flags (cp) & CFLAG_POPPEDUP)
            {
              completion_scroll_down ();
              thistab = lasttab;
            }
          break;
        case KBD_CTRL | 'v':
        case KBD_PGDN:
          if (cp == NULL)
            {
              ding ();
              break;
            }

          if (get_completion_flags (cp) & CFLAG_POPPEDUP)
            {
              completion_scroll_up ();
              thistab = lasttab;
            }
          break;
        case KBD_UP:
        case KBD_META | 'p':
          if (hp)
            {
              const char *elem = previous_history_element (hp);
              if (elem)
                {
                  if (!saved)
                    saved = astr_cpy (astr_new (), as);

                  astr_cpy_cstr (as, elem);
                }
            }
          break;
        case KBD_DOWN:
        case KBD_META | 'n':
          if (hp)
            {
              const char *elem = next_history_element (hp);
              if (elem)
                astr_cpy_cstr (as, elem);
              else if (saved)
                {
                  astr_cpy (as, saved);
                  astr_delete (saved);
                  saved = NULL;
                }
            }
          break;
        case KBD_TAB:
        got_tab:
          if (cp == NULL)
            {
              ding ();
              break;
            }

          if (lasttab != -1 && lasttab != COMPLETION_NOTMATCHED
              && get_completion_flags (cp) & CFLAG_POPPEDUP)
            {
              completion_scroll_up ();
              thistab = lasttab;
            }
          else
            {
              astr bs = astr_new ();
              astr_cpy (bs, as);
              thistab = completion_try (cp, bs, true);
              astr_delete (bs);
              switch (thistab)
                {
                case COMPLETION_MATCHED:
                case COMPLETION_MATCHEDNONUNIQUE:
                case COMPLETION_NONUNIQUE:
                  {
                    bs = astr_new ();
                    if (get_completion_flags (cp) & CFLAG_FILENAME)
                      astr_cat (bs, get_completion_path (cp));
                    astr_ncat_cstr (bs, get_completion_match (cp), get_completion_matchsize (cp));
                    if (strncmp (astr_cstr (as), astr_cstr (bs),
                                 astr_len (bs)) != 0)
                      thistab = -1;
                    astr_delete (as);
                    as = bs;
                    pos = astr_len (as);
                    break;
                  }
                case COMPLETION_NOTMATCHED:
                  ding ();
                }
            }
          break;
        case ' ':
          if (cp != NULL)
            goto got_tab;
          /* FALLTHROUGH */
        default:
          if (c > 255 || !isprint (c))
            {
              ding ();
              break;
            }
          astr_insert_char (as, pos++, c);
          if (overwrite_mode && pos != astr_len (as))
            astr_remove (as, pos, 1);
        }

      lasttab = thistab;
    }
}
Example #17
0
/*
 * This functions does some corrections and expansions to
 * the passed path:
 * - expands `~/' and `~name/' expressions;
 * - replaces `//' with `/' (restarting from the root directory);
 * - removes `..' and `.' entries.
 *
 * If something goes wrong, the string is deleted and NULL returned
 */
astr expand_path(astr path)
{
  int ret = TRUE;
  struct passwd *pw;
  const char *sp = astr_cstr(path);
  astr epath = astr_new();

  if (*sp != '/') {
    astr_cat_delete(epath, agetcwd());
    if (astr_len(epath) == 0 || *astr_char(epath, -1) != '/')
      astr_cat_char(epath, '/');
  }

  while (*sp != '\0') {
    if (*sp == '/') {
      if (*++sp == '/') {
        /* Got `//'.  Restart from this point. */
        while (*sp == '/')
          sp++;
        astr_truncate(epath, 0);
      }
      astr_cat_char(epath, '/');
    } else if (*sp == '~') {
      if (*(sp + 1) == '/') {
        /* Got `~/'. Restart from this point and insert the user's
           home directory. */
        astr_truncate(epath, 0);
        if ((pw = getpwuid(getuid())) == NULL) {
          ret = FALSE;
          break;
        }
        if (strcmp(pw->pw_dir, "/") != 0)
          astr_cat_cstr(epath, pw->pw_dir);
        ++sp;
      } else {
        /* Got `~something'.  Restart from this point and insert that
           user's home directory. */
        astr as = astr_new();
        astr_truncate(epath, 0);
        ++sp;
        while (*sp != '\0' && *sp != '/')
          astr_cat_char(as, *sp++);
        pw = getpwnam(astr_cstr(as));
        astr_delete(as);
        if (pw == NULL) {
          ret = FALSE;
          break;
        }
        astr_cat_cstr(epath, pw->pw_dir);
      }
    } else if (*sp == '.') {
      if (*(sp + 1) == '/' || *(sp + 1) == '\0') {
        ++sp;
        if (*sp == '/' && *(sp + 1) != '/')
          ++sp;
      } else if (*(sp + 1) == '.' &&
                 (*(sp + 2) == '/' || *(sp + 2) == '\0')) {
        if (astr_len(epath) >= 1 && *astr_char(epath, -1) == '/')
          astr_truncate(epath, -1);
        while (*astr_char(epath, -1) != '/' &&
               astr_len(epath) >= 1)
          astr_truncate(epath, -1);
        sp += 2;
        if (*sp == '/' && *(sp + 1) != '/')
          ++sp;
      } else
        goto got_component;
    } else {
      const char *p;
    got_component:
      p = sp;
      while (*p != '\0' && *p != '/')
        p++;
      if (*p == '\0') { /* Final filename */
        astr_cat_cstr(epath, sp);
        break;
      } else { /* Non-final directory */
        while (*sp != '/')
          astr_cat_char(epath, *sp++);
      }
    }
  }

  astr_cpy(path, epath);
  astr_delete(epath);

  if (!ret) {
    astr_delete(path);
    return NULL;
  }
  return path;
}