Cannot delete last char in insert mode

Message ID 44CB479A.8070205@cadsoft.de
State New
Headers

Commit Message

Klaus Schmidinger July 29, 2006, 11:33 a.m. UTC
  Udo Richter wrote:
> Hi list,
> 
> I've fixed a small editing bug: For menu string edit items, when in 
> insert mode, its impossible to delete the last character of the string. 
> Steps to reproduce:
> 
> - Go into some edit field: [A]BCDEF
> - Switch to insert mode  : []ABCDEF
> - Move into the string   : ABC[]DEF
> - Press yellow key       : ABC[]EF
> - Press yellow key       : ABC[]F
> - Press yellow key       : ABC[]F - nothing happens.
> 
> This doesn't happen if you move the cursor to the end once, as this will 
> insert a blind space: ABCDEF[]_
> 
> 
> The attached patch fixes this in one possible way: It deletes the last 
> char, but keeps the cursor position by inserting a whitespace:
> 
> ABC[]F -> ABC[]_
> 
> Without the whitespace, the cursor would have to move in an ugly way:
> 
> ABC[]F -> AB[]C -> A[]B -> []A -> []_
> 
> The implementation requires another quirk: To do the delete-towards-left 
> at the end of the string, just as the overwrite mode does, the delete 
> key behaves differently if it deletes a final whitespace: Instead of 
> deleting the whitespace, the second last char is deleted:
> 
> ABC[]F -> ABC[]_ -> AB[]_ -> A[]_ -> []_
> 
> 
> Cheers,
> 
> Udo
> 
> 
> ------------------------------------------------------------------------
> 
> --- vdr-1.4.1-2-orig/menuitems.c	2006-07-24 00:24:25.176897944 +0200
> +++ vdr-1.4.1/menuitems.c	2006-07-24 01:19:52.383818056 +0200
> @@ -395,6 +399,16 @@
>                      if (strlen(value) > 1) {
>                         if (!insert || pos < int(strlen(value)) - 1)
>                            memmove(value + pos, value + pos + 1, strlen(value) - pos);
> +                       else if (insert && pos == int(strlen(value)) - 1) {
> +                          // in insert mode, deleting the last char replaces it with whitespace to keep cursor pos
> +                          if (value[pos] != ' ' || pos < 1)
> +                             value[pos] = ' ';
> +                          else {
> +                             // unless the last char is already a whitespace
> +                             value[pos-1] = ' ';
> +                             value[pos] = 0;
> +                             }
> +                          }
>                         // reduce position, if we removed the last character
>                         if (pos == int(strlen(value)))
>                            pos--;

I agree with the 'if...' part of your fix, but I don't like the 'else...' part.
If I do just


it works as I would expect it.

Klaus
  

Comments

Udo Richter July 29, 2006, 12:11 p.m. UTC | #1
Klaus Schmidinger wrote:
> I agree with the 'if...' part of your fix, but I don't like the 
> 'else...' part.
> If I do just
> [..]
> it works as I would expect it.

I know it looks a bit strange. But that way the delete key does nothing 
if the cursor is at the end of the string. In overwrite mode, the delete 
key continues to delete towards left if there are no chars on the right.

By the way, in your short form, the inner if is not necessary any more:

                      if (strlen(value) > 1) {
                         if (!insert || pos < int(strlen(value)) - 1)
                            memmove(value + pos, value + pos + 1, 
strlen(value) - pos);
+                       else if (insert && pos == int(strlen(value)) - 1)
+                          // in insert mode, deleting the last 
character replaces it with a blank to keep the cursor position
+                          value[pos] = ' ';
                         // reduce position, if we removed the last 
character
                         if (pos == int(strlen(value)))
                            pos--;


Cheers,

Udo
  
Klaus Schmidinger July 30, 2006, 9:15 a.m. UTC | #2
Udo Richter wrote:
> Klaus Schmidinger wrote:
>> I agree with the 'if...' part of your fix, but I don't like the 
>> 'else...' part.
>> If I do just
>> [..]
>> it works as I would expect it.
> 
> I know it looks a bit strange. But that way the delete key does nothing 
> if the cursor is at the end of the string. In overwrite mode, the delete 
> key continues to delete towards left if there are no chars on the right.

Well, in overwrite mode the delete key deletes the character "under" the
cursor. If this was the last character in the string, the cursor has
nowhere to go but to the new last character, which is the one that was
previously "before" the cursor. In insert mode, however, the delete key
deletes the character *after* the cursor. If this was the last character,
then there's nothing more to delete. Just try this in any string entry
field, for instance the "Subject" line of your email client. These are
usually always in insert mode. If you press "Del" several times it will
delete everything after the cursor, but nothing before it.

> By the way, in your short form, the inner if is not necessary any more:
> 
>                      if (strlen(value) > 1) {
>                         if (!insert || pos < int(strlen(value)) - 1)
>                            memmove(value + pos, value + pos + 1, 
> strlen(value) - pos);
> +                       else if (insert && pos == int(strlen(value)) - 1)
> +                          // in insert mode, deleting the last 
> character replaces it with a blank to keep the cursor position
> +                          value[pos] = ' ';
>                         // reduce position, if we removed the last 
> character
>                         if (pos == int(strlen(value)))
>                            pos--;

Thanks, this makes it even better ;-)

Klaus
  
Udo Richter July 30, 2006, 1:13 p.m. UTC | #3
Klaus Schmidinger wrote:
> deletes the character *after* the cursor. If this was the last character,
> then there's nothing more to delete. Just try this in any string entry
> field, for instance the "Subject" line of your email client. These are
> usually always in insert mode. If you press "Del" several times it will
> delete everything after the cursor, but nothing before it.

Yes, of course. But thats also true in overwrite mode (where supported): 
The cursor remains after the last char, and del does nothing. And of 
course with a real keyboard there's also the backspace key.

Anyway, its not a big issue, so just do the shot patch.

Cheers,

Udo
  

Patch

--- menuitems.c 2006/07/23 09:42:17     1.46
+++ menuitems.c 2006/07/29 11:31:57
@@ -395,6 +395,11 @@ 
                      if (strlen(value) > 1) {
                         if (!insert || pos < int(strlen(value)) - 1)
                            memmove(value + pos, value + pos + 1, strlen(value) - pos);
+                       else if (insert && pos == int(strlen(value)) - 1) {
+                          // in insert mode, deleting the last character replaces it with a blank to keep the cursor position
+                          if (value[pos] != ' ' || pos < 1)
+                             value[pos] = ' ';
+                          }
                         // reduce position, if we removed the last character
                         if (pos == int(strlen(value)))
                            pos--;