/*
 *
 * zle_word.c - word-related editor functions
 *
 * This file is part of zsh, the Z shell.
 *
 * This software is Copyright 1992 by Paul Falstad
 *
 * Permission is hereby granted to copy, reproduce, redistribute or otherwise
 * use this software as long as: there is no monetary profit gained
 * specifically from the use or reproduction of this software, it is not
 * sold, rented, traded or otherwise marketed, and this copyright notice is
 * included prominently in any copy made. 
 *
 * The author make no claims as to the fitness or correctness of this software
 * for any use whatsoever, and it is provided as is. Any use of this software
 * is at the user's own risk. 
 *
 */

#define ZLE
#include "zsh.h"


void forwardword() /**/
{
	if (mult < 0) { mult = -mult; backwardword(); return; }
	while (mult--) {
		while (cs != ll && iword(line[cs])) cs++;
		if (wordflag && !mult) return;
		while (cs != ll && !iword(line[cs])) cs++;
	}
}

void viforwardword() /**/
{
	if (mult < 0) { mult = -mult; backwardword(); return; }
	while (mult--) {
		if (iident(line[cs])) while (cs != ll && iident(line[cs])) cs++;
		else while (cs != ll && !iident(line[cs]) && !iblank(line[cs])) cs++;
		if (wordflag && !mult) return;
		while (cs != ll && iblank(line[cs])) cs++;
	}
}

void viforwardblankword() /**/
{
	if (mult < 0) { mult = -mult; vibackwardblankword(); return; }
	while (mult--) {
		while (cs != ll && !iblank(line[cs])) cs++;
		if (wordflag && !mult) return;
		while (cs != ll && iblank(line[cs])) cs++;
	}
}

void emacsforwardword() /**/
{
	if (mult < 0) { mult = -mult; emacsbackwardword(); return; }
	while (mult--)
		{
		while (cs != ll && !iword(line[cs])) cs++;
		if (wordflag && !mult) return;
		while (cs != ll && iword(line[cs])) cs++;
		}
}

void viforwardblankwordend() /**/
{
	if (mult < 0) return;
	while (mult--) {
		while (cs != ll && iblank(line[cs+1])) cs++;
		while (cs != ll && !iblank(line[cs+1])) cs++;
	}
	if (cs != ll && virangeflag) cs++;
}

void viforwardwordend() /**/
{
	if (mult < 0) { mult = -mult; backwardword(); return; }
	while (mult--) {
		if (iblank(line[cs+1])) while (cs != ll && iblank(line[cs+1])) cs++;
		if (iident(line[cs+1])) while (cs != ll && iident(line[cs+1])) cs++;
		else while (cs != ll && !iident(line[cs+1]) && !iblank(line[cs+1])) cs++;
	}
	if (cs != ll && virangeflag) cs++;
}

void backwardword() /**/
{
	if (mult < 0) { mult = -mult; forwardword(); return; }
	while (mult--) {
		while (cs && !iword(line[cs-1])) cs--;
		while (cs && iword(line[cs-1])) cs--;
	}
}

void vibackwardword() /**/
{
	if (mult < 0) { mult = -mult; backwardword(); return; }
	while (mult--) {
		while (cs && iblank(line[cs-1])) cs--;
		if (iident(line[cs-1])) while (cs && iident(line[cs-1])) cs--;
		else while (cs && !iident(line[cs-1]) && !iblank(line[cs-1])) cs--;
	}
}

void vibackwardblankword() /**/
{
	if (mult < 0) { mult = -mult; viforwardblankword(); return; }
	while (mult--) {
		while (cs && iblank(line[cs-1])) cs--;
		while (cs && !iblank(line[cs-1])) cs--;
	}
}

void emacsbackwardword() /**/
{
	if (mult < 0) { mult = -mult; emacsforwardword(); return; }
	while (mult--) {
		while (cs && !iword(line[cs-1])) cs--;
		while (cs && iword(line[cs-1])) cs--;
	}
}

void backwarddeleteword() /**/
{
int x = cs;

	if (mult < 0) { mult = -mult; deleteword(); return; }
	while (mult--) {
		while (x && !iword(line[x-1])) x--;
		while (x && iword(line[x-1])) x--;
	}
	backdel(cs-x);
}

void vibackwardkillword() /**/
{
int x = cs;

        if (mult < 0) { feep(); return; }
	/* this taken from "vibackwardword" */
        while (mult--) {
                while ((x > viinsbegin) && iblank(line[x-1])) x--;
                if (iident(line[x-1])) while ((x > viinsbegin) && iident(line[x-1])) x--;
                else while ((x > viinsbegin) && !iident(line[x-1]) && !iblank(line[x-1])) x--;
        }
        /* 
        while (mult--) {
                while ( (x > viinsbegin) && (iwordsep(line[x-1]))) x--;
                while ( (x > viinsbegin) && (!iwordsep(line[x-1]))) x--;
        }
        */ 
        backkill(cs-x,1);
}

void backwardkillword() /**/
{
int x = cs;

        if (mult < 0) { mult = -mult; killword(); return; }
        while (mult--) {                       
                while (x && !iword(line[x-1])) x--;
                while (x && iword(line[x-1])) x--;
        }                                      
        backkill(cs-x,1);                      
}                                              


void upcaseword() /**/
{
int neg = mult < 0, ocs = cs;

	if (neg) mult = -mult;
	while (mult--) {
		while (cs != ll && !iword(line[cs])) cs++;
		while (cs != ll && iword(line[cs])) {
			line[cs] = tuupper(line[cs]);
			cs++;
		}
	}
	if (neg) cs = ocs;
}

void downcaseword() /**/
{
int neg = mult < 0, ocs = cs;

	if (neg) mult = -mult;
	while (mult--) {
		while (cs != ll && !iword(line[cs])) cs++;
		while (cs != ll && iword(line[cs])) {
			line[cs] = tulower(line[cs]);
			cs++;
		}
	}
	if (neg) cs = ocs;
}

void capitalizeword() /**/
{
int first;
int neg = mult < 0, ocs = cs;
	
	if (neg) mult = -mult;
	while (mult--) {
		first = 1;
		while (cs != ll && !iword(line[cs])) cs++;
		while (cs != ll && iword(line[cs])) {
			line[cs] = (first) ? tuupper(line[cs]) : tulower(line[cs]);
			first = 0;
			cs++;
		}
	}
	if (neg) cs = ocs;
}

void deleteword() /**/
{
int x = cs;

	if (mult < 0) { mult = -mult; backwarddeleteword(); return; }
	while (mult--) {
		while (x != ll && !iword(line[x])) x++;
		while (x != ll && iword(line[x])) x++;
	}
	foredel(x-cs);
}

void killword() /**/
{
int x = cs;

	if (mult < 0) { mult = -mult; backwardkillword(); return; }
	while (mult--) {
		while (x != ll && !iword(line[x])) x++;
		while (x != ll && iword(line[x])) x++;
	}
	forekill(x-cs,0);
}

void transposewords() /**/
{
int p1,p2,p3,p4,x = cs;
char *temp,*pp;
int neg = mult < 0, ocs = cs;

	if (neg) mult = -mult;
	while (mult--) {
		while (x != ll && line[x] != '\n' && !iword(line[x]))
			x++;
		if (x == ll || line[x] == '\n') {
			x = cs;
			while (x && line[x-1] != '\n' && !iword(line[x]))
				x--;
			if (!x || line[x-1] == '\n') {
				feep();
				return;
			}
		}
		for (p4 = x; p4 != ll && iword(line[p4]); p4++);
		for (p3 = p4; p3 && iword(line[p3-1]); p3--);
		if (!p3) {
			feep();
			return;
		}
		for (p2 = p3; p2 && !iword(line[p2-1]); p2--);
		if (!p2) {
			feep();
			return;
		}
		for (p1 = p2; p1 && iword(line[p1-1]); p1--);
		pp = temp = halloc(p4-p1+1);
		struncpy(&pp,UTOSCP(line+p3),p4-p3);
		struncpy(&pp,UTOSCP(line+p2),p3-p2);
		struncpy(&pp,UTOSCP(line+p1),p2-p1);
		strncpy((char *) line+p1,temp,p4-p1);
		cs = p4;
	}
	if (neg) cs = ocs;
}
