=== modified file 'uspace/app/edit/edit.c'
--- uspace/app/edit/edit.c	2011-06-08 19:01:55 +0000
+++ uspace/app/edit/edit.c	2012-04-10 15:45:05 +0000
@@ -117,6 +117,7 @@
 static void key_handle_unmod(kbd_event_t const *ev);
 static void key_handle_ctrl(kbd_event_t const *ev);
 static void key_handle_shift(kbd_event_t const *ev);
+static void key_handle_shift_ctrl(kbd_event_t const *ev);
 static void key_handle_movement(unsigned int key, bool shift);
 
 static int file_save(char const *fname);
@@ -138,9 +139,14 @@
 static void delete_char_after(void);
 static void caret_update(void);
 static void caret_move(int drow, int dcolumn, enum dir_spec align_dir);
+static void caret_move_word_left(void);
+static void caret_move_word_right(void);
 
 static bool selection_active(void);
 static void selection_sel_all(void);
+static void selection_sel_range(spt_t pa, spt_t pb);
+static void selection_sel_prev_word(void);
+static void selection_sel_next_word(void);
 static void selection_get_points(spt_t *pa, spt_t *pb);
 static void selection_delete(void);
 static void selection_copy(void);
@@ -148,6 +154,9 @@
 
 static void pt_get_sof(spt_t *pt);
 static void pt_get_eof(spt_t *pt);
+static void pt_get_sol(spt_t *cpt, spt_t *spt);
+static void pt_get_eol(spt_t *cpt, spt_t *ept);
+static bool pt_is_word_beginning(spt_t *pt);
 static int tag_cmp(tag_t const *a, tag_t const *b);
 static int spt_cmp(spt_t const *a, spt_t const *b);
 static int coord_cmp(coord_t const *a, coord_t const *b);
@@ -231,6 +240,10 @@
 			    ((ev.mods & KM_CTRL) == 0) &&
 			     (ev.mods & KM_SHIFT) != 0) {
 				key_handle_shift(&ev);
+			} else if (((ev.mods & KM_ALT) == 0) &&
+			    ((ev.mods & KM_CTRL) != 0) &&
+			     (ev.mods & KM_SHIFT) != 0) {
+				key_handle_shift_ctrl(&ev);
 			} else if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
 				key_handle_unmod(&ev);
 			}
@@ -376,6 +389,30 @@
 	case KC_A:
 		selection_sel_all();
 		break;
+	case KC_W:
+		selection_sel_prev_word();
+		selection_delete();
+		break;
+	case KC_RIGHT:
+		caret_move_word_right();
+		break;
+	case KC_LEFT:
+		caret_move_word_left();
+		break;
+	default:
+		break;
+	}
+}
+
+static void key_handle_shift_ctrl(kbd_event_t const *ev)
+{
+	switch(ev->key) {
+	case KC_LEFT:
+		selection_sel_prev_word();
+		break;
+	case KC_RIGHT:
+		selection_sel_next_word();
+		break;
 	default:
 		break;
 	}
@@ -969,7 +1006,14 @@
 
 	/* Clamp coordinates. */
 	if (drow < 0 && coord.row < 1) coord.row = 1;
-	if (dcolumn < 0 && coord.column < 1) coord.column = 1;
+	if (dcolumn < 0 && coord.column < 1) {
+		if(coord.row < 2)
+			coord.column = 1;
+		else {
+			coord.row--;
+			sheet_get_row_width(&doc.sh, coord.row, &coord.column);
+		}
+	}
 	if (drow > 0) {
 		sheet_get_num_rows(&doc.sh, &num_rows);
 		if (coord.row > num_rows) coord.row = num_rows;
@@ -997,6 +1041,40 @@
 	caret_update();
 }
 
+static void caret_move_word_left(void) 
+{
+	spt_t pt;
+
+	do {
+		caret_move(0, -1, dir_before);
+
+		tag_get_pt(&pane.caret_pos, &pt);
+
+		sheet_remove_tag(&doc.sh, &pane.sel_start);
+		sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
+	} while(!pt_is_word_beginning(&pt));
+
+	pane.rflags |= REDRAW_TEXT;
+	return;
+}
+
+static void caret_move_word_right(void) 
+{
+	spt_t pt;
+
+	do {
+		caret_move(0, 0, dir_after);
+
+		tag_get_pt(&pane.caret_pos, &pt);
+
+		sheet_remove_tag(&doc.sh, &pane.sel_start);
+		sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
+	} while(!pt_is_word_beginning(&pt));
+
+	pane.rflags |= REDRAW_TEXT;
+	return;
+}
+
 /** Check for non-empty selection. */
 static bool selection_active(void)
 {
@@ -1050,15 +1128,53 @@
 
 	pt_get_sof(&spt);
 	pt_get_eof(&ept);
+
+	selection_sel_range(spt, ept);
+}
+
+static void selection_sel_range(spt_t pa, spt_t pb)
+{
 	sheet_remove_tag(&doc.sh, &pane.sel_start);
-	sheet_place_tag(&doc.sh, &spt, &pane.sel_start);
+	sheet_place_tag(&doc.sh, &pa, &pane.sel_start);
 	sheet_remove_tag(&doc.sh, &pane.caret_pos);
-	sheet_place_tag(&doc.sh, &ept, &pane.caret_pos);
+	sheet_place_tag(&doc.sh, &pb, &pane.caret_pos);
 
 	pane.rflags |= REDRAW_TEXT;
 	caret_update();
 }
 
+static void selection_sel_prev_word(void)
+{
+	spt_t cpt, wpt, spt, ept;
+
+	selection_get_points(&spt, &ept);
+
+	tag_get_pt(&pane.caret_pos, &cpt);
+	caret_move_word_left();
+	tag_get_pt(&pane.caret_pos, &wpt);
+
+	if(spt_cmp(&spt, &cpt) == 0)
+		selection_sel_range(ept, wpt);
+	else
+		selection_sel_range(spt, wpt);
+}
+
+static void selection_sel_next_word(void)
+{
+	spt_t cpt, wpt, spt, ept;
+
+	selection_get_points(&spt, &ept);
+
+	tag_get_pt(&pane.caret_pos, &cpt);
+	caret_move_word_right();
+	tag_get_pt(&pane.caret_pos, &wpt);
+
+	if(spt_cmp(&ept, &cpt) == 0)
+		selection_sel_range(spt, wpt);
+	else
+		selection_sel_range(ept, wpt);
+}
+
 static void selection_copy(void)
 {
 	spt_t pa, pb;
@@ -1118,6 +1234,96 @@
 	sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt);
 }
 
+/** Get start-of-line s-point for given s-point cpt */
+static void pt_get_sol(spt_t *cpt, spt_t *spt)
+{
+	coord_t coord;
+
+	spt_get_coord(cpt, &coord);
+	coord.column = 1;
+
+	sheet_get_cell_pt(&doc.sh, &coord, dir_before, spt);
+}
+
+/** Get end-of-line s-point for given s-point cpt */
+static void pt_get_eol(spt_t *cpt, spt_t *ept)
+{
+	coord_t coord;
+	int row_width;
+
+	spt_get_coord(cpt, &coord);
+	sheet_get_row_width(&doc.sh, coord.row, &row_width);
+	coord.column = row_width - 1;
+
+	sheet_get_cell_pt(&doc.sh, &coord, dir_after, ept);
+}
+
+/** Check whether the spt is at a beginning of a word:
+ * - spt is at start-/end-of-file or start-/end-of-line
+ * or
+ * - spt is a printable character
+ * - the character before the spt is a delimiter
+ */
+static bool pt_is_word_beginning(spt_t *pt)
+{
+	spt_t lp, sfp, efp, slp, elp;
+	coord_t coord;
+	char *prev_char = NULL;
+	char *end_str = NULL;
+	bool ret;
+
+	pt_get_sof(&sfp);
+	pt_get_eof(&efp);
+	pt_get_sol(pt, &slp);
+	pt_get_eol(pt, &elp);
+
+	/* the spt is at the beginning or end of the file or line */
+	if((spt_cmp(&sfp, pt) == 0) || (spt_cmp(&efp, pt) == 0)
+	    || (spt_cmp(&slp, pt) == 0) || (spt_cmp(&elp, pt) == 0)) {
+		ret = true;
+		goto exit;
+	}
+
+	spt_get_coord(pt, &coord);
+
+	coord.column -= 1;
+	sheet_get_cell_pt(&doc.sh, &coord, dir_before, &lp);
+
+	prev_char = range_get_str(&lp, pt);
+	end_str = range_get_str(pt, &efp);
+	if((prev_char == NULL) || (end_str == NULL)) {
+		ret = false;
+		goto exit;
+	}
+
+	if(!letter_check(end_str[0])) {
+		/* returns false if spt itself is not a printable character */
+		ret = false;
+		goto exit;
+	}
+
+	/* 
+	 * return true if character before spt is a delimiter
+	 * else return false
+	 */
+	switch(*prev_char) {
+	case ' ':
+	case '\t':
+	case '\n':
+		ret = true;
+		break;
+	default:
+		ret = false;
+	}
+
+exit:
+	if(prev_char) {
+		free(prev_char);
+		prev_char = NULL;
+	}
+	return ret;
+}
+
 /** Compare tags. */
 static int tag_cmp(tag_t const *a, tag_t const *b)
 {

=== modified file 'uspace/app/edit/sheet.c'
--- uspace/app/edit/sheet.c	2011-06-19 14:38:59 +0000
+++ uspace/app/edit/sheet.c	2012-04-09 19:10:36 +0000
@@ -263,7 +263,7 @@
 	
 	sheet_get_cell_pt(sh, &coord, dir_before, &pt);
 	spt_get_coord(&pt, &coord);
-	*length = coord.column - 1;
+	*length = coord.column ;
 }
 
 /** Get the number of rows in a sheet. */

=== modified file 'uspace/lib/c/generic/str.c'
--- uspace/lib/c/generic/str.c	2012-03-22 10:30:51 +0000
+++ uspace/lib/c/generic/str.c	2012-04-09 19:14:27 +0000
@@ -417,6 +417,15 @@
 	return false;
 }
 
+bool letter_check(wchar_t ch)
+{
+	if(((ch >= 65) && (ch <= 90))
+	    || ((ch >= 97) && ch <= 122))
+		return true;
+
+	return false;
+}
+
 /** Compare two NULL terminated strings.
  *
  * Do a char-by-char comparison of two NULL-terminated strings.

=== modified file 'uspace/lib/c/include/str.h'
--- uspace/lib/c/include/str.h	2012-03-22 10:30:51 +0000
+++ uspace/lib/c/include/str.h	2012-04-09 16:43:31 +0000
@@ -74,6 +74,7 @@
 
 extern bool ascii_check(wchar_t ch);
 extern bool chr_check(wchar_t ch);
+extern bool letter_check(wchar_t ch);
 
 extern int str_cmp(const char *s1, const char *s2);
 extern int str_lcmp(const char *s1, const char *s2, size_t max_len);

