Annotation of embedaddon/readline/undo.c, revision 1.1.1.1

1.1       misho       1: /* readline.c -- a general facility for reading lines of input
                      2:    with emacs style editing and completion. */
                      3: 
                      4: /* Copyright (C) 1987-2012 Free Software Foundation, Inc.
                      5: 
                      6:    This file is part of the GNU Readline Library (Readline), a library
                      7:    for reading lines of text with interactive input and history editing.      
                      8: 
                      9:    Readline is free software: you can redistribute it and/or modify
                     10:    it under the terms of the GNU General Public License as published by
                     11:    the Free Software Foundation, either version 3 of the License, or
                     12:    (at your option) any later version.
                     13: 
                     14:    Readline is distributed in the hope that it will be useful,
                     15:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17:    GNU General Public License for more details.
                     18: 
                     19:    You should have received a copy of the GNU General Public License
                     20:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
                     21: */
                     22: 
                     23: #define READLINE_LIBRARY
                     24: 
                     25: #if defined (HAVE_CONFIG_H)
                     26: #  include <config.h>
                     27: #endif
                     28: 
                     29: #include <sys/types.h>
                     30: 
                     31: #if defined (HAVE_UNISTD_H)
                     32: #  include <unistd.h>           /* for _POSIX_VERSION */
                     33: #endif /* HAVE_UNISTD_H */
                     34: 
                     35: #if defined (HAVE_STDLIB_H)
                     36: #  include <stdlib.h>
                     37: #else
                     38: #  include "ansi_stdlib.h"
                     39: #endif /* HAVE_STDLIB_H */
                     40: 
                     41: #include <stdio.h>
                     42: 
                     43: /* System-specific feature definitions and include files. */
                     44: #include "rldefs.h"
                     45: 
                     46: /* Some standard library routines. */
                     47: #include "readline.h"
                     48: #include "history.h"
                     49: 
                     50: #include "rlprivate.h"
                     51: #include "xmalloc.h"
                     52: 
                     53: extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
                     54: 
                     55: /* Non-zero tells rl_delete_text and rl_insert_text to not add to
                     56:    the undo list. */
                     57: int _rl_doing_an_undo = 0;
                     58: 
                     59: /* How many unclosed undo groups we currently have. */
                     60: int _rl_undo_group_level = 0;
                     61: 
                     62: /* The current undo list for THE_LINE. */
                     63: UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
                     64: 
                     65: /* **************************************************************** */
                     66: /*                                                                 */
                     67: /*                     Undo, and Undoing                           */
                     68: /*                                                                 */
                     69: /* **************************************************************** */
                     70: 
                     71: static UNDO_LIST *
                     72: alloc_undo_entry (what, start, end, text)
                     73:      enum undo_code what;
                     74:      int start, end;
                     75:      char *text;
                     76: {
                     77:   UNDO_LIST *temp;
                     78: 
                     79:   temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
                     80:   temp->what = what;
                     81:   temp->start = start;
                     82:   temp->end = end;
                     83:   temp->text = text;
                     84: 
                     85:   temp->next = (UNDO_LIST *)NULL;
                     86:   return temp;
                     87: }
                     88: 
                     89: /* Remember how to undo something.  Concatenate some undos if that
                     90:    seems right. */
                     91: void
                     92: rl_add_undo (what, start, end, text)
                     93:      enum undo_code what;
                     94:      int start, end;
                     95:      char *text;
                     96: {
                     97:   UNDO_LIST *temp;
                     98: 
                     99:   temp = alloc_undo_entry (what, start, end, text);
                    100:   temp->next = rl_undo_list;
                    101:   rl_undo_list = temp;
                    102: }
                    103: 
                    104: /* Free an UNDO_LIST */
                    105: void
                    106: _rl_free_undo_list (ul)
                    107:      UNDO_LIST *ul;
                    108: {
                    109:   UNDO_LIST *release;
                    110: 
                    111:   while (ul)
                    112:     {
                    113:       release = ul;
                    114:       ul = ul->next;
                    115: 
                    116:       if (release->what == UNDO_DELETE)
                    117:        xfree (release->text);
                    118: 
                    119:       xfree (release);
                    120:     }
                    121: }
                    122: 
                    123: /* Free the existing undo list. */
                    124: void
                    125: rl_free_undo_list ()
                    126: {
                    127:   UNDO_LIST *release, *orig_list;
                    128: 
                    129:   orig_list = rl_undo_list;
                    130:   _rl_free_undo_list (rl_undo_list);
                    131:   rl_undo_list = (UNDO_LIST *)NULL;
                    132:   replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
                    133: }
                    134: 
                    135: UNDO_LIST *
                    136: _rl_copy_undo_entry (entry)
                    137:      UNDO_LIST *entry;
                    138: {
                    139:   UNDO_LIST *new;
                    140: 
                    141:   new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
                    142:   new->text = entry->text ? savestring (entry->text) : 0;
                    143:   return new;
                    144: }
                    145: 
                    146: UNDO_LIST *
                    147: _rl_copy_undo_list (head)
                    148:      UNDO_LIST *head;
                    149: {
                    150:   UNDO_LIST *list, *new, *roving, *c;
                    151: 
                    152:   if (head == 0)
                    153:     return head;
                    154: 
                    155:   list = head;
                    156:   new = 0;
                    157:   while (list)
                    158:     {
                    159:       c = _rl_copy_undo_entry (list);
                    160:       if (new == 0)
                    161:        roving = new = c;
                    162:       else
                    163:        {
                    164:          roving->next = c;
                    165:          roving = roving->next;
                    166:        }
                    167:       list = list->next;
                    168:     }
                    169: 
                    170:   roving->next = 0;
                    171:   return new;
                    172: }
                    173: 
                    174: /* Undo the next thing in the list.  Return 0 if there
                    175:    is nothing to undo, or non-zero if there was. */
                    176: int
                    177: rl_do_undo ()
                    178: {
                    179:   UNDO_LIST *release;
                    180:   int waiting_for_begin, start, end;
                    181:   HIST_ENTRY *cur, *temp;
                    182: 
                    183: #define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
                    184: 
                    185:   start = end = waiting_for_begin = 0;
                    186:   do
                    187:     {
                    188:       if (rl_undo_list == 0)
                    189:        return (0);
                    190: 
                    191:       _rl_doing_an_undo = 1;
                    192:       RL_SETSTATE(RL_STATE_UNDOING);
                    193: 
                    194:       /* To better support vi-mode, a start or end value of -1 means
                    195:         rl_point, and a value of -2 means rl_end. */
                    196:       if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
                    197:        {
                    198:          start = TRANS (rl_undo_list->start);
                    199:          end = TRANS (rl_undo_list->end);
                    200:        }
                    201: 
                    202:       switch (rl_undo_list->what)
                    203:        {
                    204:        /* Undoing deletes means inserting some text. */
                    205:        case UNDO_DELETE:
                    206:          rl_point = start;
                    207:          rl_insert_text (rl_undo_list->text);
                    208:          xfree (rl_undo_list->text);
                    209:          break;
                    210: 
                    211:        /* Undoing inserts means deleting some text. */
                    212:        case UNDO_INSERT:
                    213:          rl_delete_text (start, end);
                    214:          rl_point = start;
                    215:          break;
                    216: 
                    217:        /* Undoing an END means undoing everything 'til we get to a BEGIN. */
                    218:        case UNDO_END:
                    219:          waiting_for_begin++;
                    220:          break;
                    221: 
                    222:        /* Undoing a BEGIN means that we are done with this group. */
                    223:        case UNDO_BEGIN:
                    224:          if (waiting_for_begin)
                    225:            waiting_for_begin--;
                    226:          else
                    227:            rl_ding ();
                    228:          break;
                    229:        }
                    230: 
                    231:       _rl_doing_an_undo = 0;
                    232:       RL_UNSETSTATE(RL_STATE_UNDOING);
                    233: 
                    234:       release = rl_undo_list;
                    235:       rl_undo_list = rl_undo_list->next;
                    236: 
                    237:       /* If we are editing a history entry, make sure the change is replicated
                    238:         in the history entry's line */
                    239:       cur = current_history ();
                    240:       if (cur && cur->data && (UNDO_LIST *)cur->data == release)
                    241:        {
                    242:          temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
                    243:          xfree (temp->line);
                    244:          FREE (temp->timestamp);
                    245:          xfree (temp);
                    246:        }
                    247: 
                    248:       replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
                    249: 
                    250:       xfree (release);
                    251:     }
                    252:   while (waiting_for_begin);
                    253: 
                    254:   return (1);
                    255: }
                    256: #undef TRANS
                    257: 
                    258: int
                    259: _rl_fix_last_undo_of_type (type, start, end)
                    260:      int type, start, end;
                    261: {
                    262:   UNDO_LIST *rl;
                    263: 
                    264:   for (rl = rl_undo_list; rl; rl = rl->next)
                    265:     {
                    266:       if (rl->what == type)
                    267:        {
                    268:          rl->start = start;
                    269:          rl->end = end;
                    270:          return 0;
                    271:        }
                    272:     }
                    273:   return 1;
                    274: }
                    275: 
                    276: /* Begin a group.  Subsequent undos are undone as an atomic operation. */
                    277: int
                    278: rl_begin_undo_group ()
                    279: {
                    280:   rl_add_undo (UNDO_BEGIN, 0, 0, 0);
                    281:   _rl_undo_group_level++;
                    282:   return 0;
                    283: }
                    284: 
                    285: /* End an undo group started with rl_begin_undo_group (). */
                    286: int
                    287: rl_end_undo_group ()
                    288: {
                    289:   rl_add_undo (UNDO_END, 0, 0, 0);
                    290:   _rl_undo_group_level--;
                    291:   return 0;
                    292: }
                    293: 
                    294: /* Save an undo entry for the text from START to END. */
                    295: int
                    296: rl_modifying (start, end)
                    297:      int start, end;
                    298: {
                    299:   if (start > end)
                    300:     {
                    301:       SWAP (start, end);
                    302:     }
                    303: 
                    304:   if (start != end)
                    305:     {
                    306:       char *temp = rl_copy_text (start, end);
                    307:       rl_begin_undo_group ();
                    308:       rl_add_undo (UNDO_DELETE, start, end, temp);
                    309:       rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
                    310:       rl_end_undo_group ();
                    311:     }
                    312:   return 0;
                    313: }
                    314: 
                    315: /* Revert the current line to its previous state. */
                    316: int
                    317: rl_revert_line (count, key)
                    318:      int count, key;
                    319: {
                    320:   if (rl_undo_list == 0)
                    321:     rl_ding ();
                    322:   else
                    323:     {
                    324:       while (rl_undo_list)
                    325:        rl_do_undo ();
                    326: #if defined (VI_MODE)
                    327:       if (rl_editing_mode == vi_mode)
                    328:        rl_point = rl_mark = 0;         /* rl_end should be set correctly */
                    329: #endif
                    330:     }
                    331:     
                    332:   return 0;
                    333: }
                    334: 
                    335: /* Do some undoing of things that were done. */
                    336: int
                    337: rl_undo_command (count, key)
                    338:      int count, key;
                    339: {
                    340:   if (count < 0)
                    341:     return 0;  /* Nothing to do. */
                    342: 
                    343:   while (count)
                    344:     {
                    345:       if (rl_do_undo ())
                    346:        count--;
                    347:       else
                    348:        {
                    349:          rl_ding ();
                    350:          break;
                    351:        }
                    352:     }
                    353:   return 0;
                    354: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>