/* * A special insert used as the undo of delete char (C-d or DEL) * this is where the char is inserted at the point and the cursor * is NOT moved on 1 char. This MUST be a seperate function so that * INSERT + BACKSPACE are matching undo pairs * INSERT_AT + DELETE are matching undo pairs * Note: This function is only ever called by execute_undo to undo a DEL. */ void insert_at() { char_t the_char[2]; /* the inserted char plus a null */ assert(curbp->b_gap <= curbp->b_egap); if (curbp->b_gap == curbp->b_egap && !growgap(curbp, CHUNK)) return; curbp->b_point = movegap(curbp, curbp->b_point); /* overwrite if mid line, not EOL or EOF, CR will insert as normal */ if ((curbp->b_flags & B_OVERWRITE) && *input != '\r' && *(ptr(curbp, curbp->b_point)) != '\n' && curbp->b_point < pos(curbp,curbp->b_ebuf) ) { *(ptr(curbp, curbp->b_point)) = *input; if (curbp->b_point < pos(curbp, curbp->b_ebuf)) ++curbp->b_point; /* FIXME - overwite mode not handled properly for undo yet */ } else { the_char[0] = *input == '\r' ? '\n' : *input; the_char[1] = '\0'; /* null terminate */ *curbp->b_gap++ = the_char[0]; curbp->b_point = pos(curbp, curbp->b_egap); curbp->b_point--; /* move point back to where it was before, should always be safe */ /* the point is set so that and undo will DELETE the char */ add_undo(curbp, UNDO_T_INSAT, curbp->b_point, the_char, NULL); } add_mode(curbp, B_MODIFIED); }
/* Copy text from the cutbuffer into the current filestruct. */ void do_uncut_text(void) { assert(openfile->current != NULL && openfile->current->data != NULL); /* If the cutbuffer is empty, get out. */ if (cutbuffer == NULL) return; add_undo(PASTE); /* Add a copy of the text in the cutbuffer to the current filestruct * at the current cursor position. */ copy_from_filestruct(cutbuffer); update_undo(PASTE); /* Set the current place we want to where the text from the * cutbuffer ends. */ openfile->placewewant = xplustabs(); /* Mark the file as modified. */ set_modified(); /* Update the screen. */ edit_refresh_needed = TRUE; #ifndef DISABLE_COLOR reset_multis(openfile->current, FALSE); #endif #ifdef DEBUG dump_filestruct_reverse(); #endif }
/* Move text from the current filestruct into the cutbuffer. */ void do_cut_text_void(void) { #ifndef NANO_TINY add_undo(CUT); #endif do_cut_text(FALSE, FALSE); #ifndef NANO_TINY update_undo(CUT); #endif }
/* Move text from the current linestruct into the cutbuffer. */ void do_cut_text_void(void) { #ifndef NANO_TINY add_undo(CUT); #endif do_cut_text( #ifndef NANO_TINY FALSE, FALSE, FALSE #endif ); }
void backspace() { char_t the_char[7]; /* the deleted char, allow 6 unsigned chars plus a null */ int n = prev_utf8_char_size(); curbp->b_point = movegap(curbp, curbp->b_point); if (curbp->b_buf < (curbp->b_gap - (n - 1)) ) { curbp->b_gap -= n; /* increase start of gap by size of char */ add_mode(curbp, B_MODIFIED); /* record the backspaced chars in the undo structure */ memcpy(the_char, curbp->b_gap, n); the_char[n] = '\0'; /* null terminate, the backspaced char(s) */ curbp->b_point = pos(curbp, curbp->b_egap); //debug("point after bs = %ld\n", curbp->b_point); add_undo(curbp, UNDO_T_BACKSPACE, curbp->b_point, the_char, NULL); } curbp->b_point = pos(curbp, curbp->b_egap); }
/* Cut from the current cursor position to the end of the file. */ void do_cut_till_eof(void) { add_undo(CUT_EOF); do_cut_text(FALSE, TRUE, FALSE); }
/* Step through each replace word and prompt user before replacing. * Parameters real_current and real_current_x are needed in order to * allow the cursor position to be updated when a word before the cursor * is replaced by a shorter word. * * needle is the string to seek. We replace it with answer. Return -1 * if needle isn't found, else the number of replacements performed. If * canceled isn't NULL, set it to TRUE if we canceled. */ ssize_t do_replace_loop( #ifndef DISABLE_SPELLER bool whole_word_only, #endif bool *canceled, const linestruct *real_current, size_t *real_current_x, const char *needle) { ssize_t numreplaced = -1; size_t match_len; bool replaceall = FALSE; #ifndef NANO_TINY bool old_mark_set = openfile->mark_set; linestruct *top, *bot; size_t top_x, bot_x; bool right_side_up = FALSE; /* TRUE if (mark_begin, mark_begin_x) is the top of the mark, * FALSE if (current, current_x) is. */ if (old_mark_set) { /* If the mark is on, frame the region, and turn the mark off. */ mark_order((const linestruct **)&top, &top_x, (const linestruct **)&bot, &bot_x, &right_side_up); openfile->mark_set = FALSE; /* Start either at the top or the bottom of the marked region. */ if (!ISSET(BACKWARDS_SEARCH)) { openfile->current = top; openfile->current_x = (top_x == 0 ? 0 : top_x - 1); } else { openfile->current = bot; openfile->current_x = bot_x; } } #endif /* !NANO_TINY */ if (canceled != NULL) *canceled = FALSE; findnextstr_wrap_reset(); while (findnextstr( #ifndef DISABLE_SPELLER whole_word_only, #endif real_current, *real_current_x, needle, &match_len)) { int i = 0; #ifndef NANO_TINY if (old_mark_set) { /* When we've found an occurrence outside of the marked region, * stop the fanfare. */ if (openfile->current->lineno > bot->lineno || openfile->current->lineno < top->lineno || (openfile->current == bot && openfile->current_x > bot_x) || (openfile->current == top && openfile->current_x < top_x)) break; } #endif /* Indicate that we found the search string. */ if (numreplaced == -1) numreplaced = 0; if (!replaceall) { size_t xpt = xplustabs(); char *exp_word = display_string(openfile->current->data, xpt, strnlenpt(openfile->current->data, openfile->current_x + match_len) - xpt, FALSE); edit_refresh(); curs_set(0); do_replace_highlight(TRUE, exp_word); /* TRANSLATORS: This is a prompt. */ i = do_yesno_prompt(TRUE, _("Replace this instance?")); do_replace_highlight(FALSE, exp_word); free(exp_word); curs_set(1); if (i == -1) { /* We canceled the replace. */ if (canceled != NULL) *canceled = TRUE; break; } } if (i > 0 || replaceall) { /* Yes, replace it!!!! */ char *copy; size_t length_change; #ifndef NANO_TINY add_undo(REPLACE); #endif if (i == 2) replaceall = TRUE; copy = replace_line(needle); length_change = strlen(copy) - strlen(openfile->current->data); #ifndef NANO_TINY /* If the mark was on and (mark_begin, mark_begin_x) was the * top of it, don't change mark_begin_x. */ if (!old_mark_set || !right_side_up) { /* Keep mark_begin_x in sync with the text changes. */ if (openfile->current == openfile->mark_begin && openfile->mark_begin_x > openfile->current_x) { if (openfile->mark_begin_x < openfile->current_x + match_len) openfile->mark_begin_x = openfile->current_x; else openfile->mark_begin_x += length_change; bot_x = openfile->mark_begin_x; } } /* If the mark was on and (current, current_x) was the top * of it, don't change real_current_x. */ if (!old_mark_set || right_side_up) { #endif /* Keep real_current_x in sync with the text changes. */ if (openfile->current == real_current && openfile->current_x <= *real_current_x) { if (*real_current_x < openfile->current_x + match_len) *real_current_x = openfile->current_x + match_len; *real_current_x += length_change; #ifndef NANO_TINY bot_x = *real_current_x; } #endif } /* Set the cursor at the last character of the replacement * text, so searching will resume after the replacement * text. Note that current_x might be set to (size_t)-1 * here. */ #ifndef NANO_TINY if (!ISSET(BACKWARDS_SEARCH)) #endif openfile->current_x += match_len + length_change - 1; /* Clean up. */ openfile->totsize += mbstrlen(copy) - mbstrlen(openfile->current->data); free(openfile->current->data); openfile->current->data = copy; #ifndef DISABLE_COLOR /* Reset the precalculated multiline-regex hints only when * the first replacement has been made. */ if (numreplaced == 0) reset_multis(openfile->current, TRUE); #endif if (!replaceall) { #ifndef DISABLE_COLOR /* If color syntaxes are available and turned on, we * need to call edit_refresh(). */ if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) edit_refresh(); else #endif update_line(openfile->current, openfile->current_x); } set_modified(); numreplaced++; } } if (numreplaced == -1) not_found_msg(needle); #ifndef NANO_TINY if (old_mark_set) openfile->mark_set = TRUE; #endif /* If the NO_NEWLINES flag isn't set, and text has been added to the * magicline, make a new magicline. */ if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') new_magicline(); return numreplaced; }
/* Move text from the current filestruct into the cutbuffer. */ void do_cut_text_void(void) { add_undo(CUT); do_cut_text(FALSE, FALSE, FALSE); }
static bool sokoban_loop(void) { char new_spot; bool moved = true; int i = 0, button = 0, lastbutton = 0; short r = 0, c = 0; current_info.level.level = 1; load_level(); update_screen(); while (1) { moved = true; r = current_info.player.row; c = current_info.player.col; button = rb->button_get(true); add_undo(button); switch(button) { case BUTTON_OFF: /* get out of here */ return PLUGIN_OK; case SOKOBAN_UNDO: #ifdef SOKOBAN_UNDO_PRE if (lastbutton != SOKOBAN_UNDO_PRE) break; #else /* repeat can't work here for Ondio */ case SOKOBAN_UNDO | BUTTON_REPEAT: #endif /* this is UNDO */ undo(); rb->lcd_clear_display(); update_screen(); moved = false; break; case SOKOBAN_LEVEL_UP: case SOKOBAN_LEVEL_UP | BUTTON_REPEAT: /* increase level */ init_undo(); current_info.level.boxes_to_go=0; moved = true; break; case SOKOBAN_LEVEL_DOWN: case SOKOBAN_LEVEL_DOWN | BUTTON_REPEAT: /* previous level */ init_undo(); if (current_info.level.level > 1) current_info.level.level--; draw_level(); moved = false; break; case SOKOBAN_LEVEL_REPEAT: case SOKOBAN_LEVEL_REPEAT | BUTTON_REPEAT: /* same level */ init_undo(); draw_level(); moved = false; break; case BUTTON_LEFT: switch(current_info.board[r][c-1]) { case ' ': /* if it is a blank spot */ case '.': /* if it is a home spot */ new_spot = current_info.board[r][c-1]; current_info.board[r][c-1] = '@'; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = new_spot; break; case '$': switch(current_info.board[r][c-2]) { case ' ': /* going from blank to blank */ current_info.board[r][c-2] = current_info.board[r][c-1]; current_info.board[r][c-1] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = ' '; break; case '.': /* going from a blank to home */ current_info.board[r][c-2] = '%'; current_info.board[r][c-1] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = ' '; current_info.level.boxes_to_go--; break; default: moved = false; break; } break; case '%': switch(current_info.board[r][c-2]) { case ' ': /* we are going from a home to a blank */ current_info.board[r][c-2] = '$'; current_info.board[r][c-1] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = '.'; current_info.level.boxes_to_go++; break; case '.': /* if we are going from a home to home */ current_info.board[r][c-2] = '%'; current_info.board[r][c-1] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = '.'; break; default: moved = false; break; } break; default: moved = false; break; } if (moved) current_info.player.col--; break; case BUTTON_RIGHT: /* if it is a blank spot */ switch(current_info.board[r][c+1]) { case ' ': case '.': /* if it is a home spot */ new_spot = current_info.board[r][c+1]; current_info.board[r][c+1] = '@'; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = new_spot; break; case '$': switch(current_info.board[r][c+2]) { case ' ': /* going from blank to blank */ current_info.board[r][c+2] = current_info.board[r][c+1]; current_info.board[r][c+1] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = ' '; break; case '.': /* going from a blank to home */ current_info.board[r][c+2] = '%'; current_info.board[r][c+1] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = ' '; current_info.level.boxes_to_go--; break; default: moved = false; break; } break; case '%': switch(current_info.board[r][c+2]) { case ' ': /* going from a home to a blank */ current_info.board[r][c+2] = '$'; current_info.board[r][c+1] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = '.'; current_info.level.boxes_to_go++; break; case '.': current_info.board[r][c+2] = '%'; current_info.board[r][c+1] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = '.'; break; default: moved = false; break; } break; default: moved = false; break; } if (moved) current_info.player.col++; break; case BUTTON_UP: switch(current_info.board[r-1][c]) { case ' ': /* if it is a blank spot */ case '.': /* if it is a home spot */ new_spot = current_info.board[r-1][c]; current_info.board[r-1][c] = '@'; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = new_spot; break; case '$': switch(current_info.board[r-2][c]) { case ' ': /* going from blank to blank */ current_info.board[r-2][c] = current_info.board[r-1][c]; current_info.board[r-1][c] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = ' '; break; case '.': /* going from a blank to home */ current_info.board[r-2][c] = '%'; current_info.board[r-1][c] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = ' '; current_info.level.boxes_to_go--; break; default: moved = false; break; } break; case '%': switch(current_info.board[r-2][c]) { case ' ': /* we are going from a home to a blank */ current_info.board[r-2][c] = '$'; current_info.board[r-1][c] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = '.'; current_info.level.boxes_to_go++; break; case '.': /* if we are going from a home to home */ current_info.board[r-2][c] = '%'; current_info.board[r-1][c] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = '.'; break; default: moved = false; break; } break; default: moved = false; break; } if (moved) current_info.player.row--; break; case BUTTON_DOWN: switch(current_info.board[r+1][c]) { case ' ': /* if it is a blank spot */ case '.': /* if it is a home spot */ new_spot = current_info.board[r+1][c]; current_info.board[r+1][c] = '@'; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = new_spot; break; case '$': switch(current_info.board[r+2][c]) { case ' ': /* going from blank to blank */ current_info.board[r+2][c] = current_info.board[r+1][c]; current_info.board[r+1][c] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = ' '; break; case '.': /* going from a blank to home */ current_info.board[r+2][c] = '%'; current_info.board[r+1][c] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = ' '; current_info.level.boxes_to_go--; break; default: moved = false; break; } break; case '%': switch(current_info.board[r+2][c]) { case ' ': /* going from a home to a blank */ current_info.board[r+2][c] = '$'; current_info.board[r+1][c] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = '.'; current_info.level.boxes_to_go++; break; case '.': /* going from a home to home */ current_info.board[r+2][c] = '%'; current_info.board[r+1][c] = current_info.board[r][c]; current_info.board[r][c] = current_info.player.spot; current_info.player.spot = '.'; break; default: moved = false; break; } break; default: moved = false; break; } if (moved) current_info.player.row++; break; default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) return PLUGIN_USB_CONNECTED; moved = false; break; } if (button != BUTTON_NONE) lastbutton = button; if (moved) { current_info.level.moves++; rb->lcd_clear_display(); update_screen(); } /* We have completed this level */ if (current_info.level.boxes_to_go == 0) { current_info.level.level++; /* clear undo stats */ init_undo(); rb->lcd_clear_display(); if (current_info.level.level > current_info.max_level) { rb->lcd_putsxy(10, 20, "You WIN!!"); rb->lcd_set_drawmode(DRMODE_COMPLEMENT); for (i = 0; i < 30000 ; i++) { rb->lcd_fillrect(0, 0, 111, 63); rb->lcd_update(); button = rb->button_get(false); if (button && ((button & BUTTON_REL) != BUTTON_REL)) break; } rb->lcd_set_drawmode(DRMODE_SOLID); return PLUGIN_OK; } load_level(); update_screen(); } } /* end while */ return PLUGIN_OK; }