lynx-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

lynx-dev Final dev15 patch for TEXTAREA edit feature (I hope)


From: Kim DeVaughn
Subject: lynx-dev Final dev15 patch for TEXTAREA edit feature (I hope)
Date: Thu, 4 Feb 1999 11:03:18 -0800

Hopefully, this will be the last full patch for the TEXTAREA edit
feature that I'll be making against -dev.15, but I wanted to try
and get it into the next (dev.16) release, as it fixes quite a few
things.

Please back off (-R) any of my previous patches for TEXTAREA edit,
or apply to clean -dev.15 source.

In addition to the earlier fixes, this patch:

 1. Handles the renumbering of link number tags [nnn], when the tag
    itself is split across two lines (see below).

 2. Scrolling down, going to the bottom of the document, etc, now
    work properly, when the TEXTAREA is expanded beyond the bottom
    of the (original) screen display.

 3. Hitting the reset buton is now handled properly WRT the "old"
    text in expansion lines (now *always* empty).

 4. Attempting to edit (^Ve) a TEXT field (not a TEXTAREA), is now
    blocked, with the user getting an error msg.

 5. The function call now returns the number of lines that the cursor
    should be moved from its current position, to end up on the first
    blank line of any trailing empty lines in the TEXTAREA (there will
    always be one).

    I'm still looking into how to accomplish that task, but now it is
    decoupled from the editind feature, per se.  Thanks to those who
    have offered suggestions about how this might be accomplished.


Still on my TODO list (related to this feature) are:  a) implement the
rest of item (5) above;  b) provide a command to allow inserting a file
directly into a TEXTAREA, without having to invoke the editor;  and c)
provide a command that will expand the TEXTAREA by some given number of
blank lines (say 10), again bypassing the use of an editor (which won't
allow the addition of trailing blank lines anyway).


Notes on item (1):

    I looked into preventing such tag-splitting in the first place,
    but it seemed like that would be an uglier hack, than just going
    ahead and handling them.

    There is a small problem (which does NOT affect the renumbering
    itself) when there is a line crossing tag, and some anchor in the
    line on either side of the split changes from a 3 digit to a 4
    digit number, as a result of TEXTAREA expansion.

    In such a case, when one or more of the anchors is selected in
    the line on either side of the split, that anchor's text *may*
    get displaced by some small number character positions, leaving
    the anchor's display looking like "HHelp" or "Helplp" for example.

    This is purely a visual artifact.  The renumbering is correct,
    and other lines which do not include a split tag, but whose
    tag numbers went from (say) 3 to 4 digits, behave properly when
    repositioned.

    I wasn't able to figure out the positioning algorithm used for
    positioning the anchors of line crossing tags, but it seems neither
    simple, nor constant ... more of an attempt to keep both lines
    centered WRT eachother.  Or some such.

    As may be ... since in real life, this is likely to be encountered
    only rarely, and since it is a purly visual thing (which a ^L will
    "fix" until such anchors are again selected), I'm not planning on
    delving into this any further.

/kim


Against unpatched 2.8.2dev.15:

diff -uNr lynx-2.8.2-dev.15+kd.orig/LYMessages_en.h 
lynx-2.8.2-dev.15+kd/LYMessages_en.h
--- lynx-2.8.2-dev.15+kd.orig/LYMessages_en.h   Thu Jan 28 08:31:29 1999
+++ lynx-2.8.2-dev.15+kd/LYMessages_en.h        Thu Feb  4 07:07:49 1999
@@ -49,6 +49,8 @@
 /* Forms messages */
 #define FORM_LINK_TEXT_MESSAGE \
  gettext("(Text entry field) Enter text.  Use UP or DOWN arrows or tab to move 
off.")
+#define FORM_LINK_TEXTAREA_MESSAGE \
+ gettext("(Textarea) Enter text. Use UP/DOWN arrows or TAB to move off (^Ve 
for editor).")
 #define FORM_LINK_TEXT_UNM_MSG \
  gettext("UNMODIFIABLE form text field.  Use UP or DOWN arrows or tab to move 
off.")
 #define FORM_LINK_TEXT_SUBMIT_MESSAGE \
@@ -429,7 +431,9 @@
 #define COULD_NOT_ACCESS_DIR gettext("Could not access directory.")
 #define COULD_NOT_LOAD_DATA gettext("Could not load data.")
 #define CANNOT_EDIT_REMOTE_FILES \
- gettext("Lynx cannot currently (E)dit remote WWW files")
+ gettext("Lynx cannot currently (e)dit remote WWW files.")
+#define CANNOT_EDIT_FIELD \
+ gettext("This field cannot be (e)dited with an external editor.")
 #define RULE_INCORRECT gettext("Bad rule")
 #define RULE_NEEDS_DATA gettext("Insufficient operands:")
 #define NOAUTH_TO_EDIT_FILE gettext("You are not authorized to edit this 
file.")
diff -uNr lynx-2.8.2-dev.15+kd.orig/lynx_help/keystrokes/alt_edit_help.html 
lynx-2.8.2-dev.15+kd/lynx_help/keystrokes/alt_edit_help.html
--- lynx-2.8.2-dev.15+kd.orig/lynx_help/keystrokes/alt_edit_help.html   Thu Feb 
 4 08:08:09 1999
+++ lynx-2.8.2-dev.15+kd/lynx_help/keystrokes/alt_edit_help.html        Tue Feb 
 2 01:35:06 1999
@@ -32,7 +32,7 @@
      EOL    Go to end   of  line  -  Ctrl-E, End,  Select
 
      DELP   Delete prev     char  -  Ctrl-H, DELETE, Remove
-     DELN   Delete next [*] char  -  Ctrl-D
+     DELN   Delete next [1] char  -  Ctrl-D
      DELPW  Delete prev     word  -  Ctrl-R
      DELNW  Delete next     word  -  Ctrl-T
      DELBL  Delete to beg of line -  Ctrl-X
@@ -41,11 +41,14 @@
      UPPER  Upper case the line   -  Ctrl-^
      LOWER  Lower case the line   -  Ctrl-_
 
-     LKCMD  Invoke cmd prompt     -  Ctrl-V (in form text fields, only)
+     LKCMD  Invoke cmd prompt     -  Ctrl-V (in form text areas, only) [2]
 
-[*] "next" means the character "under" a box or underline style cursor; it
+[1] "next" means the character "under" a box or underline style cursor; it
      means "to the immediate right of" an I-beam (between characters) type
      cursor.
+
+[2]  Follow Ctrl-V with the key bound to the EDIT function (default: "e"),
+     to edit the textarea using an external editor.
 </pre>
 </body>
 </html>
diff -uNr lynx-2.8.2-dev.15+kd.orig/lynx_help/keystrokes/edit_help.html 
lynx-2.8.2-dev.15+kd/lynx_help/keystrokes/edit_help.html
--- lynx-2.8.2-dev.15+kd.orig/lynx_help/keystrokes/edit_help.html       Thu Feb 
 4 08:08:09 1999
+++ lynx-2.8.2-dev.15+kd/lynx_help/keystrokes/edit_help.html    Tue Feb  2 
01:35:06 1999
@@ -35,7 +35,7 @@
      EOL    Go to end   of  line  -  Ctrl-E, End,  Select
 
      DELP   Delete prev     char  -  Ctrl-H, DELETE, Remove
-     DELN   Delete next [*] char  -  Ctrl-D, Ctrl-R
+     DELN   Delete next [1] char  -  Ctrl-D, Ctrl-R
      DELPW  Delete prev     word  -  Ctrl-B
      DELNW  Delete next     word  -  Ctrl-F
      DELEL  Delete to end of line -  Ctrl-_
@@ -43,12 +43,15 @@
      UPPER  Upper case the line   -  Ctrl-T
      LOWER  Lower case the line   -  Ctrl-K
 
-     LKCMD  Invoke cmd prompt     -  Ctrl-V (in form text fields, only)
+     LKCMD  Invoke cmd prompt     -  Ctrl-V (in form text areas, only) [2]
      SWMAP  Switch input keymap   -  Ctrl-^
 
-[*] "next" means the character "under" a box or underline style cursor; it
+[1] "next" means the character "under" a box or underline style cursor; it
      means "to the immediate right of" an I-beam (between characters) type
      cursor.
+
+[2]  Follow Ctrl-V with the key bound to the EDIT function (default: "e"),
+     to edit the text area using an external editor.
 </pre>
 </body>
 </html>
diff -uNr lynx-2.8.2-dev.15+kd.orig/src/GridText.c 
lynx-2.8.2-dev.15+kd/src/GridText.c
--- lynx-2.8.2-dev.15+kd.orig/src/GridText.c    Thu Jan 28 08:31:29 1999
+++ lynx-2.8.2-dev.15+kd/src/GridText.c Thu Feb  4 06:01:48 1999
@@ -8688,14 +8688,269 @@
     return(FALSE);
 }
 
+
+/*
+ *  Re-render the text of a tagged ("[123]") HTLine (arg1), with the tag
+ *  number incremented by some value (arg5).  The re-rendered string may
+ *  be allowed to expand in the event of a tag width change (eg, 99 -> 100)
+ *  as controlled by arg6 (CHOP or NOCHOP).  Arg4 is either (the address
+ *  of) a value which must match, in order for the tag to be incremented,
+ *  or (the address of) a 0-value, which matches any value, and will cause
+ *  any valid tag to be incremented.  Arg2 is a pointer to the first/only
+ *  Anchor that exists on the line (if any); we may need to adjust their
+ *  position(s) on the line.  Arg3 when non-0 indicates the number of new
+ *  digits that were added to the 2nd line in a line crossing pair.
+ *
+ *  All tags fields in a line which individually match an expected new value,
+ *  are incremented.  Line crossing [tags] are handled (PITA).
+ *
+ *  Untagged or improperly tagged lines are not altered.
+ *
+ *  Returns the number of chars added to the original string's length, if
+ *  any.   KED  02/03/99
+ */
+PRIVATE int increment_tagged_htline ARGS6(
+        HTLine *,       ht,
+       TextAnchor *,   a,
+       int *,          lx_val,
+       int *,          old_val,
+       int,            incr,
+       int,            mode)
+{
+    char    buf[MAX_LINE];
+    char  lxbuf[MAX_LINE * 2];
+
+    TextAnchor *st_anchor  = a;
+    TextAnchor *nxt_anchor;
+
+    char *p   = ht->data;
+    char *s   = buf;
+    char *lx  = lxbuf;
+    char *t;
+
+    BOOLEAN   plx    = FALSE;
+    BOOLEAN   valid;
+
+    int   val;
+    int   n;
+    int   new_n;
+    int   pre_n;
+    int   fixup = 0;
+
+
+    /*
+     *  Cleanup for the 2nd half of a line crosser, whose number of tag
+     *  digits grew by some number of places (usually 1, when it does
+     *  happen, though it *could* be more).  The tag chars were already
+     *  rendered into the 2nd line of the pair, but the positioning and
+     *  other effects haven't been rippled through any other anchors on
+     *  the (2nd) line.  So we do that here, as a special case, since
+     *  the part of the tag that's in the 2nd line of the pair, will not
+     *  be found by the tag string parsing code.  Double PITA.
+     *
+     *  [see comments below on line crosser caused problems]
+     */
+    if (*lx_val != 0) {
+       nxt_anchor = st_anchor;
+       while ((nxt_anchor) && (nxt_anchor->line_num == a->line_num)) {
+          nxt_anchor->line_pos += *lx_val;
+          nxt_anchor = nxt_anchor->next;
+       }
+       fixup  = *lx_val;
+      *lx_val = 0;
+       st_anchor = st_anchor->next;
+    }
+
+
+    /*
+     *  Walk thru the line looking for tags (ie, "[nnn]" strings).
+     */
+    while (*p != '\0') {
+        if (*p != '[') {
+          *s++ = *p++;
+          continue;
+
+       } else {
+          *s++ = *p++;
+          t = p;
+          n = 0;
+          valid = TRUE;   /* p = t = byte after ']' */
+
+          /*
+           *  Make sure there are only digits between "[" and "]".
+           */
+          while  (*t != ']')  {
+              if (*t == '\0') {  /* uhoh - we have a potential line crosser */
+                 valid = FALSE;
+                 plx   = TRUE;
+                 break;
+              }
+              if (isdigit (*t++) != 0) {
+                 n++;
+                 continue;
+              } else {
+                 valid = FALSE;
+                 break;
+              }
+          }
+
+          /*
+           *  It the format is OK, we check to see if the value is what
+           *  we expect.  If not, we have a random [nn] string in the text,
+           *  and leave it alone.
+           *
+           *  [It is *possible* to have a false match here, *if* there are
+           *   two identical [nn] strings (including the numeric value of
+           *   nn), one of which is the [tag], and the other being part of
+           *   a document.  In such a case, the 1st [nn] string will get
+           *   incremented; the 2nd one won't, which makes it a 50-50 chance
+           *   of being correct, if and when such an unlikely juxitposition
+           *   of text ever occurs.  Further validation tests of the [nnn]
+           *   string are probably not possible, since little of the actual
+           *   anchor-associated-text is retained in the TextAnchor or the
+           *   FormInfo structs.  Fortunately, I think the current method is
+           *   more than adequate to weed out 99.99% of any possible false
+           *   matches, just as it stands.  Caveat emptor.]
+           */
+          if ((valid) && (n > 0)) {
+             val = atoi (p);
+             if ((val == *old_val) || (*old_val == 0)) {
+                if (*old_val != 0)
+                   (*old_val)++;
+                val += incr;
+                sprintf (s, "%d", val);
+                new_n = strlen (s);
+                s += new_n;
+                p += n;
+
+                /*
+                 *  If the number of digits in an existing [tag] increased
+                 *  (eg, [99] --> [100], etc), we need to "adjust" its
+                 *  horizontal position, and that of all subsequant tags
+                 *  that may be on the same line.  PITA.
+                 *
+                 *  [This seems to work as long as a tag isn't a line
+                 *   crosser; when it is, the position of anchors on either
+                 *   side of the split tag, seem to "float" and try to be
+                 *   as "centered" as possible.  Which means that simply
+                 *   incrementing the line_pos by the fixed value of the
+                 *   number of digits that got added to some tag in either
+                 *   line doesn't work quite right, and the text for (say)
+                 *   a button may get stomped on by another copy of itself,
+                 *   but offset by a few chars, when it is selected (eg,
+                 *   "Box Office" may end up looking like "BoBox Office" or
+                 *   "Box Officece", etc.
+                 *
+                 *   Dunno how to fix that behavior ATT, but at least the
+                 *   tag numbers themselves are correct.  -KED  /\oo/\ ]
+                 */
+                if (new_n -= n) {
+                   nxt_anchor = st_anchor;
+                   while ((nxt_anchor)                           &&
+                          (nxt_anchor->line_num == a->line_num)) {
+                       nxt_anchor->line_pos += new_n;
+                       nxt_anchor = nxt_anchor->next;
+                   }
+                   st_anchor = st_anchor->next;
+                }
+             }
+          }
+
+          /*
+           *  Unfortunately, valid [tag] strings *can* be split across two
+           *  lines.  Perhaps it would be best to just prevent that from
+           *  happening, but a look into that code, makes me wonder.  Anyway,
+           *  we can handle such tags without *too* much trouble in here [I
+           *  think], though since such animals are rather rare, it makes it
+           *  a bit difficult to test thoroughly (ie, Beyond here, there be
+           *  Dragons).
+           *
+           *  We use lxbuf[] to deal with the two lines involved.
+           */
+          if (plx) {
+             strcpy (lx, p);      /* <- 1st part of a possible lx'ing tag  */
+             pre_n = strlen (p);  /* count of 1st part chars in this line  */
+             strcat (lx, ht->next->data);  /* tack on NEXT line            */
+
+             t = lx;
+             n = 0;
+             valid = TRUE;
+
+             /*
+              *  Go hunting again for just digits, followed by a tag end ']'.
+              */
+             while (*t != ']') {
+                 if (isdigit (*t++) != 0) {
+                    n++;
+                    continue;
+                 } else {
+                    valid = FALSE;
+                    break;
+                 }
+             }
+
+             /*
+              *  It *looks* like a line crosser; now we value test it to
+              *  find out for sure [but see the "false match" warning,
+              *  above], and if it matches, increment it into the buffer,
+              *  along with the 2nd line's text.
+              */
+             if ((valid) && (n > 0)) {
+                val = atoi (lx);
+                if ((val == *old_val) || (*old_val == 0)) {
+                   if (*old_val != 0)
+                      (*old_val)++;
+                   val += incr;
+                   sprintf (lx, "%d", val);
+                   new_n = strlen (lx);
+                   strcat (lx, strchr (ht->next->data, ']'));
+
+                   /*
+                    *  We keep the the same number of chars from the
+                    *  adjusted tag number in the current line; any
+                    *  extra chars due to a digits increase, will be
+                    *  stuffed into the next line.
+                    *
+                    *  Keep track of any digits added, for the next
+                    *  pass through.
+                    */
+                   s   = strncpy (s, lx, pre_n) + pre_n;
+                   lx += pre_n;
+                   strcpy (ht->next->data, lx);
+
+                  *lx_val = new_n - n;
+                }
+             }
+             break;  /* had an lx'er, so we're done with this line */
+          }
+       }
+    }
+
+    *s = '\0';
+
+    n = strlen (ht->data);
+    if (mode == CHOP)
+       *(buf + n) = '\0';
+    strcpy (ht->data, buf);
+
+    return (strlen (buf) - n + fixup);
+}
+
+
 /*
  *  Transfer the initial contents of a TEXTAREA to a temp file, invoke the
  *  user's editor on that file, then transfer the contents of the resultant
  *  edited file back into the TEXTAREA (expanding the size of the area, if
- *  required).   KED  01/26/99
+ *  required).
+ *
+ *  Returns the number of lines that the cursor should be moved so that it
+ *  will end up on the 1st blank line of whatever number of trailing blank
+ *  lines there are in the TEXTAREA (there will *always* be at least one).
+ *
+ *  --KED  02/01/99
  */
-PUBLIC void HText_ExtEditForm ARGS1(
-            struct link *, form_link)
+PUBLIC int HText_ExtEditForm ARGS1(
+           struct link *,  form_link)
 {
     struct stat stat_info;
 
@@ -8704,16 +8959,18 @@
 
     TextAnchor *anchor_ptr;
     TextAnchor *start_anchor = NULL;
-    TextAnchor *end_anchor  = NULL;
-    BOOLEAN    firstanchor = TRUE;
-    int        orig_cnt    = 0;
-    int        line_cnt    = 1;
+    TextAnchor *end_anchor   = NULL;
+    BOOLEAN    firstanchor  = TRUE;
+    int         entry_line   = form_link->anchor_line_num;
+    int         exit_line    = 0;
+    int        orig_cnt     = 0;
+    int        line_cnt     = 1;
 
     FormInfo   *form    = form_link->form;
     char       *areaname = form->name;
     int        form_num = form->number;
 
-    HTLine     *htline;
+    HTLine     *htline  = NULL;
 
     TextAnchor *a = 0;
     FormInfo   *f = 0;
@@ -8722,17 +8979,26 @@
     char       *ebuf;
     char       *tbuf = NULL;
     char       *line;
+    char       *lp;
     char       *cp;
     char       *p;
+    char       *s;
+    int         curr_tag;
+    int         line_adj = 0;
+    int         tag_adj  = 0;
     int        len;
     int        i;
     int        n;
+    int         lx;
     size_t     size;
 
-    ed_temp = (char *)malloc(LY_MAXPATH);
+
+    CTRACE(tfp, "GridText: entered HText_ExtEditForm()\n");
+
+    ed_temp = (char *) malloc (LY_MAXPATH);
     if ((fp = LYOpenTemp (ed_temp, "", "w")) == 0) {
        FREE(ed_temp);
-       return;
+       return (0);
     }
 
     /*
@@ -8761,13 +9027,13 @@
            !strcmp (anchor_ptr->input_field->name, areaname))   {
 
            if (firstanchor) {
-               firstanchor = FALSE;
+               firstanchor = FALSE;
                start_anchor = anchor_ptr;
            }
            orig_cnt++;
 
            /*
-            * Write the anchor's text to the temp edit file.
+            *  Write the anchors' text to the temp edit file.
             */
            fputs (anchor_ptr->input_field->value, fp);
            fputc ('\n', fp);
@@ -8781,6 +9047,8 @@
     }
     fclose (fp);
 
+    CTRACE(tfp, "GridText: TEXTAREA name=|%s| dumped to tempfile\n", areaname);
+
     /*
      * Go edit the TEXTAREA temp file.
      */
@@ -8798,14 +9066,16 @@
 #endif
     free (tbuf);
 
+    CTRACE(tfp, "GridText: returned from editor (%s)\n", editor);
+
     /*
-     * Read back the edited temp file, whacking off any trailing whitespace.
+     * Read back the edited temp file.
      */
-    if (stat (ed_temp, &stat_info) < 0
-     || !S_ISREG(stat_info.st_mode)
-     || (size = stat_info.st_size) == 0) {
+    if ((stat (ed_temp, &stat_info) < 0)   ||
+       !S_ISREG(stat_info.st_mode)        ||
+        ((size = stat_info.st_size) == 0)) {
        size = 0;
-       ebuf = malloc(1);
+       ebuf = (char *) calloc (1, 1);
     } else {
        ebuf = (char *) calloc (size + 1, (sizeof(char)));
 
@@ -8819,58 +9089,102 @@
     /*
      * Nuke any blank lines from the end of the edited data.
      */
-    while ((size != 0) && isspace(ebuf[size-1]))
+    while ((size != 0) && (isspace (ebuf[size-1]) || (ebuf[size-1] == '\0')))
        ebuf[--size] = '\0';
 
     /*
      * Copy each line from the temp file into the corresponding anchor
-     * struct, removing any trailing whitespace.  Add new lines to the
-     * TEXTAREA if needed.  (Always leave the user with a blank line at
-     * the end of the TEXTAREA.)
+     *  struct, removing any trailing whitespace, expanding any embedded
+     *  tab's, and substituting a printable char for any other embedded
+     *  control chars.  Add new lines to the TEXTAREA if needed.  (Always
+     *  leave the user with a blank line at the end of the TEXTAREA.)
      */
-    if ((line = (char *) malloc (MAX_LINE)) == 0)
+    if (((line = (char *) malloc (MAX_LINE)) == 0) ||
+       ((tbuf = (char *) malloc (MAX_LINE)) == 0))
        outofmem(__FILE__, "HText_ExtEditForm");
 
     anchor_ptr = start_anchor;
+
     len = 0;
-    p = ebuf;
+    lp  = ebuf;
 
-    while ((line_cnt <= orig_cnt) || (*p) || ((len != 0) && (*p == '\0'))) {
+    while ((line_cnt <= orig_cnt) || (*lp) || ((len != 0) && (*lp == '\0'))) {
 
-       if ((cp = strchr (p, '\n')) != 0)
-          len = cp - p;
+       if ((cp = strchr (lp, '\n')) != 0)
+          len = cp - lp;
        else
-          len = strlen (p);
+          len = strlen (lp);
 
-       strncpy(line, "\0", MAX_LINE);
-       strncpy(line, p, len);
-
-       cp = p;
+       strncpy (line, lp, len);
+       *(line + len) = '\0';
 
        /*
         *  Whack off trailing whitespace from the line.
-        *
-        *  [maybe use isspace() here instead, too (portable ?)]
         */
-       for (size = MAX_LINE, p = line + size - 1; size != 0; p--, size--) {
+       for (i = len, p = line + (len - 1); i != 0; p--, i--) {
            if (isspace(*p))
-               *p = '\0';
+              *p = '\0';
            else
-               break;
+              break;
+       }
+
+       if (strlen (line) != 0) {
+          /*
+           *  Expand any tab's, since they won't render properly in a
+           *  TEXTAREA.
+           *
+           *  [is that "by spec", or just a "lynxism" ? ... as may be, it
+           *   seems they may cause other problems, too ... haven't really
+           *   looked into that very deeply though]
+           */
+          p = line;
+          s = tbuf;
+
+          while (*p) {
+              if ((cp = strchr (p, '\t')) != 0) {
+                 i  = cp - p;
+                 s  = (strncpy (s, p, i))      + i;
+                 n  = TABSTOP - (i % TABSTOP);
+                 s  = (strncpy (s, SPACES, n)) + n;
+                 p += (i + 1);
+
+              } else {
+
+                 strcpy (s, p);
+                 break;
+              }
+          }
+
+          /*
+           *  Replace control chars with something printable.  Note that
+           *  we leave any chars above 0x7f alone (ie, no translation is
+           *  performed ... the assumption being that the charset used in
+           *  the editor is compatible with the charset rendered by lynx).
+           */
+          for (p = line, s = tbuf; *s != '\0'; p++, s++)
+              *p = (*s < ' ') ? SPLAT : *s;
+          *p = '\0';
        }
 
+
        /*
         *  If there are more lines in the edit buffer than were in the
         *  original TEXTAREA, we need to add some new lines, continuing
         *  until the edit buffer is empty.
         *
-        *  [cloning structs should me moved to a seperate fn(), or three]
+        *  [cloning structs could be moved to a seperate fn(), or three]
         */
        if (line_cnt > orig_cnt) {
 
           /*
            *  Find line in the text that matches ending anchorline of
            *  the TEXTAREA.
+           *
+           *  [Yes, Virginia ... we *do* have to go thru this for each
+           *   anchor being added, since there is NOT a 1-to-1 mapping
+           *   between anchors and htlines.  I suppose we could create
+           *   YAS (Yet Another Struct), but there are too many structs{}
+           *   floating around in here, as it is.  IMNSHO.]
            */
           for (htline = HTMainText->last_line->next, i = 0;
                i != end_anchor->line_num;
@@ -8880,12 +9194,12 @@
            *  Clone and initialize the structs needed to add a new
            *  TEXTAREA anchor.
            */
-          if ((a = (TextAnchor *) calloc (1, sizeof(*a))) == 0
-           || (f = (FormInfo   *) calloc (1, sizeof(*f))) == 0
-           || (l = (HTLine     *) calloc (1, LINE_SIZE(MAX_LINE))) == 0)
-               outofmem(__FILE__, "HText_ExtEditForm");
+          if (((a = (TextAnchor *) calloc (1, sizeof(*a)))          == 0)  ||
+              ((f = (FormInfo   *) calloc (1, sizeof(*f)))          == 0)  ||
+              ((l = (HTLine     *) calloc (1, LINE_SIZE(MAX_LINE))) == 0))
+             outofmem(__FILE__, "HText_ExtEditForm");
 
-          /*  Init all the fields in the new anchor.  */
+          /*  Init all the fields in the new TextAnchor.  */
           a->next             = end_anchor->next;
           a->number           = end_anchor->number;
           a->start            = end_anchor->start +
@@ -8893,7 +9207,7 @@
           a->line_pos         = end_anchor->line_pos;
           a->extent           = end_anchor->extent;
           a->line_num         = end_anchor->line_num + 1;
-          StrAllocCopy (a->hightext, end_anchor->hightext);
+          StrAllocCopy (a->hightext,  end_anchor->hightext);
           StrAllocCopy (a->hightext2, end_anchor->hightext2);
           a->hightext2offset  = end_anchor->hightext2offset;
           a->link_type        = end_anchor->link_type;
@@ -8902,16 +9216,16 @@
           a->inUnderline      = end_anchor->inUnderline;
           a->anchor           = end_anchor->anchor;
 
-          /*  Just the (seemingly) relevant fields in the FormInfo.    */
+          /*  Just the (seemingly) relevant fields in the new FormInfo.  */
           StrAllocCopy (f->name, end_anchor->input_field->name);
           f->number           = end_anchor->input_field->number;
           f->type             = end_anchor->input_field->type;
-          StrAllocCopy (f->orig_value, end_anchor->input_field->orig_value);
+          StrAllocCopy (f->orig_value, "");
           f->size             = end_anchor->input_field->size;
           f->maxlength        = end_anchor->input_field->maxlength;
           f->no_cache         = end_anchor->input_field->no_cache;
 
-          /*  Init all the fields in the new HTLine (but see the #if).  */
+          /*  Init all the fields in the new HTLine (but see the #if).   */
           l->next             = htline->next;
           l->prev             = htline;
           l->offset           = htline->offset;
@@ -8922,9 +9236,13 @@
           /* dup styles[] if needed [no need in TEXTAREA (?); leave 0's] */
           l->numstyles        = htline->numstyles;
 #endif
-          for (i = 0; htline->data[i] != '\0'; i++)
-              l->data[i] = htline->data[i];
-          l->data[i] = '\0';
+          strcpy (l->data,      htline->data);
+          if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) {
+             a->number++;
+             curr_tag = 0;  /* 0 matches any [tag] number */
+             lx       = 0;
+             increment_tagged_htline (l, a, &lx, &curr_tag, 1, CHOP);
+          }
 
           /*
            *  Link in the new TextAnchor and make it current; link in
@@ -8938,54 +9256,119 @@
           htline = l;
        }
 
+
        /*
         *  Finally copy the new line from the edit buffer into the anchor.
         */
        StrAllocCopy(anchor_ptr->input_field->value, line);
 
+
        /*
         *  And do the next line, for the next anchor ...
         */
-       p = cp + len;
-       if (*p) p++;
+       lp += len;
+       if (*lp) lp++;
+
+       if (len > 0)
+          exit_line = 0;
+       else if (exit_line == 0)
+          exit_line = anchor_ptr->line_num;
 
        end_anchor = anchor_ptr;
        anchor_ptr = anchor_ptr->next;
+       curr_tag   = anchor_ptr->number;
+
+       if (htline != NULL)
+          htline   = htline->next;
 
        line_cnt++;
     }
 
+    CTRACE(tfp, "GridText: edited text inserted into lynx struct's\n");
 
     /*
      * If new anchors were added, we need to ripple the new line numbers
-     * (and char counts ?) thru the subsequent anchors.  Also update the
-     * HText counts.
+     * (and char counts ?) thru the subsequent anchors.  If form lines
+     *  are getting tagged, we need to update the displayed tag values
+     *  to match (which means re-rendering them ...sigh).  Finally update
+     *  the HText counts.
      *
      * [dunno if the char counts really need to be done, or if we're using
-     *  the proper values ... seems OK though ...]
+     *  the exactly proper values ... seems to be OK though ...]
      */
     if ((n = (line_cnt - 1) - orig_cnt) > 0) {
         i = (end_anchor->input_field->size + 1) * n;
 
         while (anchor_ptr) {
+           if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED)
+              anchor_ptr->number += n;
            anchor_ptr->line_num  += n;
            anchor_ptr->start     += i;
            anchor_ptr             = anchor_ptr->next;
         }
-        HTMainText->Lines += n;
-        HTMainText->chars += i;
+       anchor_ptr = end_anchor;
+
+       /*
+        *  If a number tag (eg, "[177]") is itself broken across a line
+        *  boundary, this fixup only partially works.  While the tag
+        *  numbering is done properly across the pair of lines, the
+        *  horizontal positioning on *either* side of the split, can get
+        *  out of sync by a char or two when it gets selected.  See [com
+        *  ments] in  increment_tagged_htline()  for some more detail.
+        *
+        *  I suppose THE fix is to prevent such tag-breaking in the first
+        *  place (dunno where yet, though).  Ah well ... at least the tag
+        *  numbers are correct from top to bottom now.
+        *
+        *  All that said, about the only time this will be a problem in
+        *  *practice*, is when a page has near 1000 links or more (possibly
+        *  after a TEXTAREA expansion), and has line crossing tag(s), and
+        *  the tag numbers in a line crosser go from initially all 3 digit
+        *  numbers, to some mix of 3 and 4 digits (or all 4 digits) as a
+        *  result of the expansion process.  Oh, and you need a "clump" of
+        *  anchors all on the same lines.
+        *
+        *  Yes, it *can* happen, but in real life, it probably won't be
+        *  seen very much ...
+        */
+       if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) {
+          lx = 0;
+          while (htline != HTMainText->last_line->next) {
+              while (anchor_ptr) {
+                  if ((anchor_ptr->number - n) == curr_tag)
+                     break;
+                  else
+                     anchor_ptr = anchor_ptr->next;
+              }
+              line_adj = increment_tagged_htline (htline, anchor_ptr, &lx,
+                                                  &curr_tag, n, NOCHOP);
+              htline->size += line_adj;
+              tag_adj      += line_adj;
+              htline = htline->next;
+          }
+       }
+
+       nlinks                         += n;
+        HTMainText->Lines              += n;
+       HTMainText->last_anchor_number += n;
+        HTMainText->chars              += (i + tag_adj);
+
+       if (n) more = TRUE;
     }
 
-    /*** MOVE the cursor to some logical place ... 1st/only blank line in
-     ***         the textarea seems most reasonable; lacking that, the end
-     ***         line of the textarea; lacking that ... the 1st line of the
-     ***         textarea; else leave it where it is (as we now do).
-     ***/
+    CTRACE(tfp, "GridText: struct's adjusted - exiting HText_ExtEditForm()\n");
 
     free (line);
     free (ebuf);
+    free (tbuf);
     LYRemoveTemp (ed_temp);
     free (ed_temp);
 
-    return;
+    /*
+     *  Return the offset needed to move the cursor from its current
+     *  (on entry) line number, to the 1st blank line of the trailing
+     *  (group of) blank line(s), which is where we want to be.  Let
+     *  the caller deal with moving us there, however ... :-) ...
+     */
+    return (exit_line - entry_line);
 }
diff -uNr lynx-2.8.2-dev.15+kd.orig/src/GridText.h 
lynx-2.8.2-dev.15+kd/src/GridText.h
--- lynx-2.8.2-dev.15+kd.orig/src/GridText.h    Thu Jan 28 08:31:29 1999
+++ lynx-2.8.2-dev.15+kd/src/GridText.h Tue Feb  2 01:35:07 1999
@@ -27,6 +27,13 @@
 
 #define IsSpecialAttrChar(a)  ((a > '\002') && (a <= '\010'))
 
+#define TABSTOP 8
+#define SPACES  "        "  /* must be at least TABSTOP spaces long */
+#define SPLAT   '.'
+
+#define NOCHOP 0
+#define CHOP   1
+
 /* just for information:
 US-ASCII control characters <32 which are not defined in Unicode standard
 =00    U+0000  NULL
@@ -248,7 +255,7 @@
        HTParentAnchor *        anchor,
        CONST char *            full_address));
 
-extern void HText_ExtEditForm PARAMS((
-       struct link *   form_link));
+extern int HText_ExtEditForm PARAMS((
+       struct link *   form_link));
 
 #endif /* LYGRIDTEXT_H */
diff -uNr lynx-2.8.2-dev.15+kd.orig/src/LYForms.c 
lynx-2.8.2-dev.15+kd/src/LYForms.c
--- lynx-2.8.2-dev.15+kd.orig/src/LYForms.c     Mon Jan 18 04:29:20 1999
+++ lynx-2.8.2-dev.15+kd/src/LYForms.c  Tue Feb  2 01:35:07 1999
@@ -311,8 +311,10 @@
                    }
                    break;
                case F_TEXT_TYPE:
-               case F_TEXTAREA_TYPE:
                    statusline(FORM_LINK_TEXT_MESSAGE);
+                   break;
+               case F_TEXTAREA_TYPE:
+                   statusline(FORM_LINK_TEXTAREA_MESSAGE);
                    break;
                default:
                    break;
diff -uNr lynx-2.8.2-dev.15+kd.orig/src/LYKeymap.c 
lynx-2.8.2-dev.15+kd/src/LYKeymap.c
--- lynx-2.8.2-dev.15+kd.orig/src/LYKeymap.c    Thu Jan 28 08:31:29 1999
+++ lynx-2.8.2-dev.15+kd/src/LYKeymap.c Tue Feb  2 01:35:07 1999
@@ -577,7 +577,7 @@
 { "WHEREIS",           "search within the current document" },
 { "NEXT",              "search for the next occurence" },
 { "COMMENT",           "send a comment to the author of the current document" 
},
-{ "EDIT",              "edit the current document" },
+{ "EDIT",              "edit the current document or a form's textarea" },
 { "INFO",              "display information on the current document and link" 
},
 { "PRINT",             "display choices for printing the current document" },
 { "ADD_BOOKMARK",      "add to your personal bookmark list" },
@@ -607,7 +607,7 @@
 { "SWITCH_DTD",                "switch between two ways of parsing HTML" },
 { "ELGOTO",            "edit the current link's URL or ACTION and go to it" },
 { "CHANGE_LINK",       "force reset of the current link on the page" },
-{ "EDITTEXTAREA",      "use defined external editor to edit the text area" },
+{ "EDITTEXTAREA",      "use an external editor to edit a form's textarea" },
 #ifdef USE_EXTERNALS
 { "EXTERN",            "run external program with url" },
 #endif
diff -uNr lynx-2.8.2-dev.15+kd.orig/src/LYMainLoop.c 
lynx-2.8.2-dev.15+kd/src/LYMainLoop.c
--- lynx-2.8.2-dev.15+kd.orig/src/LYMainLoop.c  Thu Jan 28 08:31:29 1999
+++ lynx-2.8.2-dev.15+kd/src/LYMainLoop.c       Thu Feb  4 07:19:38 1999
@@ -269,6 +269,7 @@
     BOOLEAN override_LYresubmit_posts = FALSE;
     unsigned int len;
     int i;
+    int n;
 
 #ifdef DIRED_SUPPORT
     char *tp = NULL;
@@ -1449,12 +1450,17 @@
                            statusline(FORM_LINK_RESET_MESSAGE);
                        break;
                    case F_TEXT_TYPE:
-                   case F_TEXTAREA_TYPE:
                        if (links[curdoc.link].form->disabled == YES)
                            statusline(FORM_LINK_TEXT_UNM_MSG);
                        else
                            statusline(FORM_LINK_TEXT_MESSAGE);
                        break;
+                   case F_TEXTAREA_TYPE:
+                       if (links[curdoc.link].form->disabled == YES)
+                           statusline(FORM_LINK_TEXT_UNM_MSG);
+                       else
+                           statusline(FORM_LINK_TEXTAREA_MESSAGE);
+                       break;
                    }
                } else {
                    statusline(NORMAL_LINK_MESSAGE);
@@ -4142,6 +4148,28 @@
                break;
            }
 
+           /*
+            *  If we're in a forms TEXTAREA, invoke the editor on it.
+            */
+           if (links[curdoc.link].type       == WWW_FORM_LINK_TYPE &&
+               links[curdoc.link].form->type == F_TEXTAREA_TYPE)   {
+              cmd = LYK_EDIT_TEXTAREA;
+              goto new_cmd;
+           }
+
+           /*
+            *  If we're in a forms TEXT type, tell user the request
+            *  is bogus (though in reality, without this trap, if the
+            *  document with the TEXT field is local, the editor *would*
+            *  be invoked on the source .html file; eg, the o(ptions)
+            *  form tempfile).
+            */
+           if (links[curdoc.link].type       == WWW_FORM_LINK_TYPE &&
+               links[curdoc.link].form->type == F_TEXT_TYPE)       {
+              HTUserMsg(CANNOT_EDIT_FIELD);
+              break;
+           }
+
 #ifdef DIRED_SUPPORT
            /*
             *  Allow the user to edit the link rather
@@ -4304,25 +4332,37 @@
                break;
            }
 
-               /* is curent link part of a textarea */
-           if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
-               links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
+           /*
+            *  See if the current link is in a form TEXTAREA.
+            */
+           if (links[curdoc.link].type       == WWW_FORM_LINK_TYPE &&
+               links[curdoc.link].form->type == F_TEXTAREA_TYPE)   {
 
                /* stop screen */
                stop_curses();
 
-               HText_ExtEditForm (&links[curdoc.link]);
+               n = HText_ExtEditForm (&links[curdoc.link]);
+
+               lines_in_file = HText_getNumOfLines();
+
+               /*
+                *  TODO: Move cursor "n" lines from the current line to
+                *        position it on the 1st trailing blank line in
+                *        the now edited TEXTAREA.  If the target line/
+                *        anchor requires us to scroll up/down, position
+                *        the target in the approximate center of the
+                *        screen.
+                */
+
+               /* curdoc.link += n;*/  /* works, except for page crossing, */
+                                       /* damnit; why is nothing ever easy */
 
                /* start screen */
                start_curses();
                refresh_screen = TRUE;
 
-               /*
-               cmd = LYK_REFRESH;
-               goto new_cmd;
-               */
-
            } else {
+
                HTInfoMsg (NOT_IN_TEXTAREA);
            }
            break;
diff -uNr lynx-2.8.2-dev.15+kd.orig/src/structdump.h 
lynx-2.8.2-dev.15+kd/src/structdump.h
--- lynx-2.8.2-dev.15+kd.orig/src/structdump.h  Thu Jan 28 08:31:29 1999
+++ lynx-2.8.2-dev.15+kd/src/structdump.h       Tue Feb  2 01:35:07 1999
@@ -9,24 +9,24 @@
 /* usage: DUMPSTRUCT_LINK(link_ptr, "message"); */
 #define   DUMPSTRUCT_LINK(L,X) \
 CTRACE(tfp, "\n" \
-            "KED:     link_ptr=%08x  sizeof=%d  ["X"]\n" \
-            "link       struct {\n" \
-            "           *lname=%08x\n" \
-            "            lname=|%s|\n" \
-            "          *target=%08x\n" \
-            "           target=|%s|\n" \
-            "        *hightext=%08x\n" \
-            "         hightext=|%s|\n" \
-            "       *hightext2=%08x\n" \
-            "        hightext2=|%s|\n" \
-            " hightext2_offset=%d\n"   \
-            "      inUnderline=%1x\n"  \
-            "               lx=%d\n"   \
-            "               ly=%d\n"   \
-            "             type=%d\n"   \
-            "    anchor_number=%d\n"   \
-            "  anchor_line_num=%d\n"   \
-            "            *form=%08x\n" \
+            "KED:     link_ptr=0x%08x  sizeof=%d  ["X"]\n" \
+            "link       struct {\n"      \
+            "           *lname=0x%08x\n" \
+            "            lname=|%s|\n"   \
+            "          *target=0x%08x\n" \
+            "           target=|%s|\n"   \
+            "        *hightext=0x%08x\n" \
+            "         hightext=|%s|\n"   \
+            "       *hightext2=0x%08x\n" \
+            "        hightext2=|%s|\n"   \
+            " hightext2_offset=%d\n"     \
+            "      inUnderline=%1x\n"    \
+            "               lx=%d\n"     \
+            "               ly=%d\n"     \
+            "             type=%d\n"     \
+            "    anchor_number=%d\n"     \
+            "  anchor_line_num=%d\n"     \
+            "            *form=0x%08x\n" \
             "}\n", \
             (L), sizeof(*((L))), \
             (L)->lname, (L)->lname, (L)->target, (L)->target, \
@@ -39,25 +39,25 @@
 /* usage: DUMPSTRUCT_ANCHOR(anchor_ptr, "message"); */
 #define   DUMPSTRUCT_ANCHOR(A,X) \
 CTRACE(tfp, "\n" \
-            "KED:   anchor_ptr=%08x  sizeof=%d  ["X"]\n" \
-            "TextAnchor struct {\n"    \
-            "            *next=%08x\n" \
-            "           number=%d\n"   \
-            "            start=%d\n"   \
-            "         line_pos=%d\n"   \
-            "           extent=%d\n"   \
-            "         line_num=%d\n"   \
-            "        *hightext=%08x\n" \
-            "         hightext=|%s|\n" \
-            "       *hightext2=%08x\n" \
-            "        hightext2=|%s|\n" \
-            "  hightext2offset=%d\n"   \
-            "        link_type=%d\n"   \
-            "     *input_field=%08x\n" \
-            "      input_field=|%s|\n" \
-            "      show_anchor=%1x\n"  \
-            "      inUnderline=%1x\n"  \
-            "          *anchor=%08x\n" \
+            "KED:   anchor_ptr=0x%08x  sizeof=%d  ["X"]\n" \
+            "TextAnchor struct {\n"      \
+            "            *next=0x%08x\n" \
+            "           number=%d\n"     \
+            "            start=%d\n"     \
+            "         line_pos=%d\n"     \
+            "           extent=%d\n"     \
+            "         line_num=%d\n"     \
+            "        *hightext=0x%08x\n" \
+            "         hightext=|%s|\n"   \
+            "       *hightext2=0x%08x\n" \
+            "        hightext2=|%s|\n"   \
+            "  hightext2offset=%d\n"     \
+            "        link_type=%d\n"     \
+            "     *input_field=0x%08x\n" \
+            "      input_field=|%s|\n"   \
+            "      show_anchor=%1x\n"    \
+            "      inUnderline=%1x\n"    \
+            "          *anchor=0x%08x\n" \
             "}\n", \
             (A), sizeof(*((A))), \
             (A)->next, (A)->number, (A)->start, (A)->line_pos, \
@@ -72,35 +72,35 @@
 /* usage: DUMPSTRUCT_FORM(forminfo_ptr, "message"); */
 #define   DUMPSTRUCT_FORMINFO(F,X) \
 CTRACE(tfp, "\n" \
-            "KED: forminfo_ptr=%08x  sizeof=%d  ["X"]\n" \
-            "FormInfo   struct {\n"    \
-            "            *name=%08x\n" \
-            "             name=|%s|\n" \
-            "           number=%d\n"   \
-            "             type=%d\n"   \
-            "           *value=%08x\n" \
-            "            value=|%s|\n" \
-            "      *orig_value=%08x\n" \
-            "       orig_value=|%s|\n" \
-            "             size=%d\n"   \
-            "        maxlength=%d\n"   \
-            "            group=%d\n"   \
-            "        num_value=%d\n"   \
-            "           hrange=%d\n"   \
-            "           lrange=%d\n"   \
-            "     *select_list=%08x\n" \
-            "    submit_action=|%s|\n" \
-            "    submit_method=%d\n"   \
-            "   submit_enctype=|%s|\n" \
-            "     submit_title=|%s|\n" \
-            "         no_cache=%1x\n"  \
-            "  cp_submit_value=|%s|\n" \
-            "orig_submit_value=|%s|\n" \
-            "           size_l=%d\n"   \
-            "         disabled=%d\n"   \
-            "          name_cs=%d\n"   \
-            "         value_cs=%d\n"   \
-            "        accept_cs=|%s|\n" \
+            "KED: forminfo_ptr=0x%08x  sizeof=%d  ["X"]\n" \
+            "FormInfo   struct {\n"      \
+            "            *name=0x%08x\n" \
+            "             name=|%s|\n"   \
+            "           number=%d\n"     \
+            "             type=%d\n"     \
+            "           *value=0x%08x\n" \
+            "            value=|%s|\n"   \
+            "      *orig_value=0x%08x\n" \
+            "       orig_value=|%s|\n"   \
+            "             size=%d\n"     \
+            "        maxlength=%d\n"     \
+            "            group=%d\n"     \
+            "        num_value=%d\n"     \
+            "           hrange=%d\n"     \
+            "           lrange=%d\n"     \
+            "     *select_list=0x%08x\n" \
+            "    submit_action=|%s|\n"   \
+            "    submit_method=%d\n"     \
+            "   submit_enctype=|%s|\n"   \
+            "     submit_title=|%s|\n"   \
+            "         no_cache=%1x\n"    \
+            "  cp_submit_value=|%s|\n"   \
+            "orig_submit_value=|%s|\n"   \
+            "           size_l=%d\n"     \
+            "         disabled=%d\n"     \
+            "          name_cs=%d\n"     \
+            "         value_cs=%d\n"     \
+            "        accept_cs=|%s|\n"   \
             "}\n", \
             (F), sizeof(*((F))), \
             (F)->name, (F)->name, (F)->number, (F)->type, \
@@ -117,17 +117,17 @@
 /* usage: DUMPSTRUCT_LINE(htline_ptr, "message"); */
 #define   DUMPSTRUCT_LINE(L,X) \
 CTRACE(tfp, "\n" \
-            "KED: htline_ptr=%08x  sizeof=%d  ["X"]\n" \
-            "HTLine struct {\n"    \
-            "        *next=%08x\n" \
-            "        *prev=%08x\n" \
-            "       offset=%d\n"   \
-            "         size=%d\n"   \
-            "  split_after=%1x\n"  \
-            "       bullet=%1x\n"  \
-            "nodef U_C_S\n"        \
-            "       data[]=%08x\n" \
-            "         data=|%s|\n" \
+            "KED: htline_ptr=0x%08x  sizeof=%d  ["X"]\n" \
+            "HTLine struct {\n"      \
+            "        *next=0x%08x\n" \
+            "        *prev=0x%08x\n" \
+            "       offset=%d\n"     \
+            "         size=%d\n"     \
+            "  split_after=%1x\n"    \
+            "       bullet=%1x\n"    \
+            "nodef U_C_S\n"          \
+            "       data[]=0x%08x\n" \
+            "         data=|%s|\n"   \
             "}\n", \
             (L), sizeof(*((L))), \
             (L)->next, (L)->prev, (L)->offset, (L)->size, (L)->split_after, \
##--eof--##

reply via email to

[Prev in Thread] Current Thread [Next in Thread]