/*
 * The routines in this file implement commands that work word at a time.
 * There are all sorts of word mode commands. If I do any sentence and/or
 * paragraph mode commands, they are likely to be put in this file.
 */

#include  <stdio.h>
#include  "ed.h"

#define CHAR unsigned char


/*
 * Return TRUE if the character at dot is a character that is considered to be
 * part of a word. The word character list is hard coded. Should be setable.
 */
inword()
{
 register CHAR c;

 if (curwp->w_doto == llength(curwp->w_dotp)) return (FALSE);
 c = lgetc(curwp->w_dotp, curwp->w_doto);
 if (c>='a' && c<='z') return (TRUE);
 if (c>='A' && c<='Z') return (TRUE);
 if (c>='0' && c<='9') return (TRUE);
 if (c>=0x80) return (TRUE);
 return (FALSE);
}

CHAR cap(c)
CHAR c;
{
 if ( (('a'<=c) && (c<='z')) || (((CHAR)0xE0<=c) && (c<=(CHAR)0xFE)) ) {
  c -= 32;
 }
 return(c);
}

CHAR ceil(c)
CHAR c;
{
 if (('A'<=c && c<='Z') || ((CHAR)'À'<=c && c<=(CHAR)'Þ')) {
  c += 32;
 }
 return(c);
}

/*
 * Move the cursor backward by "n" words. All of the details of motion are
 * performed by the "backchar" and "forwchar" routines. Error if you try to
 * move beyond the buffers.
 */
backword(f, n)
{
 if (n < 0)
  return (forwword(f, -n));
 if (backchar(FALSE, 1) == FALSE)
  return (FALSE);
 while (n--) {
  while (inword() == FALSE) {
   if (backchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
  while (inword()) {
   if (backchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
 }
 return (forwchar(FALSE, 1));
}

/*
 * Move the cursor forward by the specified number of words. All of the motion
 * is done by "forwchar". Error if you try and move beyond the buffer's end.
 */
forwword(f, n)
{
 if (n < 0)
  return (backword(f, -n));
 while (n--) {
  while (inword() == FALSE) {
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
  while (inword()) {
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
 }
 return (TRUE);
}

/*
 * Move the cursor forward by the specified number of words. As you move,
 * convert any characters to upper case. Error if you try and move beyond the
 * end of the buffer. Bound to "M-U".
 */
upperword(f, n)
{

 if (n < 0)
  return (FALSE);
 while (n--) {
  while (inword() == FALSE) {
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
  while (inword()) {
   lputc(curwp->w_dotp,curwp->w_doto,cap(lgetc(curwp->w_dotp,curwp->w_doto)));
   lchange(WFEDIT);
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
 }
 return (TRUE);
}

/*
 * Move the cursor forward by the specified number of words. As you move
 * convert characters to lower case. Error if you try and move over the end of
 * the buffer. Bound to "M-L".
 */
lowerword(f, n)
{

 if (n < 0)
  return (FALSE);
 while (n--) {
  while (inword() == FALSE) {
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
  while (inword()) {
   lputc(curwp->w_dotp,curwp->w_doto,ceil(lgetc(curwp->w_dotp, curwp->w_doto)));
   lchange(WFEDIT);
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
 }
 return (TRUE);
}

/*
 * Move the cursor forward by the specified number of words. As you move
 * convert the first character of the word to upper case, and subsequent
 * characters to lower case. Error if you try and move past the end of the
 * buffer. Bound to "M-C".
 */
capword(f, n)
{

 if (n < 0)
  return (FALSE);
 while (n--) {
  while (inword() == FALSE) {
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
  }
  if (inword()) {
   lputc(curwp->w_dotp,curwp->w_doto,cap(lgetc(curwp->w_dotp,curwp->w_doto)));
   lchange(WFEDIT);
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
   return(lowerword(FALSE,1));
  }
 }
 return (TRUE);
}

/*
 * Kill forward by "n" words. Remember the location of dot. Move forward by
 * the right number of words. Put dot back where it was and issue the kill
 * command for the right number of characters. Bound to "M-D".
 */
delfword(f, n)
{
 register int size;
 register LINE *dotp;
 register int doto;

 if (n < 0)
  return (FALSE);
 dotp = curwp->w_dotp;
 doto = curwp->w_doto;
 size = 0;
 while (n--) {
  while (inword() == FALSE) {
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
   ++size;
  }
  while (inword() != FALSE) {
   if (forwchar(FALSE, 1) == FALSE)
    return (FALSE);
   ++size;
  }
 }
 curwp->w_dotp = dotp;
 curwp->w_doto = doto;
 return (ldelete(size, TRUE));
}

/*
 * Kill backwards by "n" words. Move backwards by the desired number of words,
 * counting the characters. When dot is finally moved to its resting place,
 * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
 */
delbword(f, n)
{
 register int size;

 if (n < 0)
  return (FALSE);
 if (backchar(FALSE, 1) == FALSE)
  return (FALSE);
 size = 0;
 while (n--) {
  while (inword() == FALSE) {
   if (backchar(FALSE, 1) == FALSE)
    return (FALSE);
   ++size;
  }
  while (inword()) {
   if (backchar(FALSE, 1) == FALSE)
    return (FALSE);
   ++size;
  }
 }
 if (forwchar(FALSE, 1) == FALSE)
  return (FALSE);
 return (ldelete(size, TRUE));
}

/*
 * Ohm need the word at the cursor position. We can easily get
 * that word into the buffer 'lastWord'.
 */
char lastWord[255];

void getword(f,n)
{
  int doto, ok, c;
  LINE *dotp;

  doto = curwp->w_doto;
  dotp = curwp->w_dotp;

 /* Go to the start of the word */
  while ((inword() == FALSE) && backchar(FALSE,1));
  while (inword() && (ok = backchar(FALSE,1)));
  if (ok)
    forwchar(FALSE,1);

  ok = TRUE;
  c = 0;
  while (ok && inword()) {
    lastWord[c++] = lgetc(curwp->w_dotp, curwp->w_doto);
    ok = forwchar(FALSE, 1);
  }
  lastWord[c] = '\0';
  curwp->w_doto = doto;
  curwp->w_dotp = dotp;
  mlwrite("lastWord ist '%s'", lastWord);
}
