forms.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:44k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /* forms.c - forms handling for html+
  2. ParseHTML() creates a linked list of forms. Each form has a linked
  3. list of fields. This file includes routines for drawing fields,
  4. handling mouse clicks/drags and key presses on fields, plus sending
  5. the contents of forms to HTTP servers.
  6. When resizing windows, it is important to keep the existing form
  7. data structures as otherwise the current values of fields will be
  8. lost and overridden by the original starting values. This requires
  9. the global new_form to be set to false. It should be set to true
  10. when reading new documents. In addition, The browser history list
  11. needs to preserve the form data structures so that they can be
  12. reused upon backtracking to restore previous field values.
  13. The desire to evolve to a wysiwyg editor means that its a bad idea
  14. to have pointers into the paint stream as this would be expensive
  15. to update when users edit the html document source . Consequently,
  16. one has to search the form structure to find fields that need to
  17. be redrawn under programatic control, e.g. unsetting of radio
  18. buttons. Note that anyway, the y-position of a field is unresolved
  19. when it is added to the paint stream, and only becomes fixed when
  20. the end of the line is reached. A compromise is to cache the
  21. baseline position when painting each field and trash the cache
  22. each time the user alters the document.
  23. Another complication is the need to save current field values
  24. when following a link to another document, as otherwise there
  25. is now way of restoring them when the user backtracks to the
  26. document containing the form. A simple approach is to save the
  27. linked list of forms in memory as part of a memory resident
  28. history list. Note for local links, the same form data should
  29. be used, rather than recreating the list from new. The corollary
  30. is that the list should only be freed when backtracking the
  31. document containing the form or reloading the same.
  32. Note that in many cases a sequence of form interactions with
  33. a server causes a state change in the server (e.g. updating a
  34. database) and hence is not simply reversed by backtracking in
  35. the normal way. In this case it makes sense to avoid pushing
  36. intermediate steps onto the history stack, e.g. when submitting
  37. the form. This probably requires the document or server to
  38. disable the history nechanism via suitable attributes.
  39. */
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <ctype.h>
  43. #include "www.h"
  44. #include "types.h"
  45. #include "neweditor.h"
  46. extern Display *display;
  47. extern int screen;
  48. extern Window win;
  49. extern GC disp_gc, gc_fill;
  50. extern Cursor hourglass;
  51. extern int UsePaper;
  52. extern int debug;  /* controls display of errors */
  53. extern int document;  /* HTMLDOCUMENT or TEXTDOCUMENT */
  54. extern int busy;
  55. extern int OpenURL;
  56. extern int IsIndex;
  57. extern int FindStr;
  58. extern int Authorize;
  59. extern char *FindNextStr;
  60. extern int SaveFile;
  61. extern int sbar_width;
  62. extern int statusHeight;
  63. extern int ToolBarHeight;
  64. extern unsigned long windowColor;
  65. extern unsigned int win_width, win_height, tileWidth, tileHeight;
  66. extern unsigned long textColor, labelColor, windowTopShadow,
  67.                      strikeColor, windowBottomShadow, statusColor, windowColor;
  68. /*
  69.     The current top line is displayed at the top of the window,the pixel
  70.     offset is the number of pixels from the start of the document.
  71. */
  72. extern char *buffer;            /* the start of the document buffer */
  73. extern long PixelOffset;        /* the pixel offset to top of window */
  74. extern int PixelIndent;
  75. extern Doc *CurrentDoc;
  76. extern XFontStruct *pFontInfo;
  77. extern XFontStruct *Fonts[FONTS];
  78. extern int LineSpacing[FONTS], BaseLine[FONTS], StrikeLine[FONTS];
  79. extern int preformatted;
  80. extern int font;  /* index into Fonts[] array */
  81. extern int above, below;
  82. extern XRectangle displayRect; /* clipping limits for painting html */
  83. Form *forms = NULL;
  84. Field *focus;   /* which field has focus (NULL if none do) */
  85. int cursorpos = 5; /* cursor position in characters */
  86. Bool TextFieldFocus = FALSE;
  87. /*
  88.    The next 3 pointers indicate records to reuse for next form/field/option
  89.    when resizing a document or during 2nd pass thru table data. If NULL the
  90.    corresponding record is created from scratch
  91. */
  92. Form *next_form = NULL;
  93. Field *next_field = NULL;
  94. Option *next_option = NULL;
  95. /* version of strdup that copes with null string pointers */
  96. char *strsav(char *s)
  97. {
  98.     if (s)
  99.         return strdup(s);
  100.     return NULL;
  101. }
  102. /* version of strdup for use with non-terminated strings */
  103. char *strdup2(char *s, int len)
  104. {
  105.     char *str;
  106.     str = (char *)malloc(len + 1);
  107.     memcpy(str, s, len);
  108.     str[len] = '';
  109.     return str;
  110. }
  111. Form *FindForm(Form *forms,char *link)
  112. {
  113.     Form *form_link;
  114.     for (form_link = forms; form_link != NULL; form_link = form_link->next)
  115.     {
  116.        if ( form_link->action == link)
  117.    return(form_link);
  118.     };
  119.     return(NULL); /* failed */
  120. }
  121. Field *FindField(Form *form,int type, char *name, int namelen)
  122. {
  123.     Field *field_link;
  124.     for( field_link = form->fields; field_link != NULL ; field_link = field_link->next)
  125.     {
  126.         if ( field_link->type == type )  /* check type then name... assume it's enough */
  127.   if ( type == RADIOBUTTON)
  128.   {
  129.       if( name == field_link->name)
  130.           return(field_link);
  131.   }
  132.   else
  133.       if ( strncasecmp( name, field_link->name, namelen) == 0 )
  134.           return(field_link);
  135.     };
  136.     return(NULL);
  137. }
  138. int FieldCount(Form *form)
  139. {
  140.     int n;
  141.     Field *field;
  142.     n = 0;
  143.     field = form->fields;
  144.     while (field)
  145.     {
  146.         ++n;
  147.         field = field->next;
  148.     }
  149.     return n;
  150. }
  151. void FreeForms(void)
  152. {
  153.     Option *option;
  154.     Form *form;
  155.     Field *fields, *field;
  156.     next_form = NULL;
  157.     next_field = NULL;
  158.     next_option = NULL;
  159.     while (forms != NULL)
  160.     {
  161.         form = forms;
  162.         forms = forms->next;
  163.         fields = form->fields;
  164.         while (fields)
  165.         {
  166.             field = fields;
  167.     /* Free(field->name); --Spif name is only a copy of pointer 13-Oct-95 */
  168.             Free(field->value);
  169.     /* --Spif we must clear image */
  170.     if (field->image != NULL)
  171.     {
  172.         free( field->image->pixels );
  173. free( field->image->url );
  174. free( field->image );
  175.     };
  176.             fields = fields->next;
  177.     
  178.             while (field->options)
  179.             {
  180.                 option = field->options;
  181.                 if (option->label)
  182.                     Free(option->label);
  183.                 field->options = option->next;
  184.                 Free(option);
  185.             }
  186.             Free(field);
  187.         }
  188.         if (form->action)
  189.             Free(form->action);
  190.         Free(form);
  191.     }
  192. }
  193. /* scroll field up/down by delta - this is called
  194.    to adjust y offset of field - not to paint fields */
  195. void ScrollForms(long delta)
  196. {
  197.     Form *form;
  198.     Field *field;
  199.     for (form = forms; form; form = form->next)
  200.     {
  201.         for (field = form->fields; field; field = field->next)
  202.             if (field->baseline >= 0 && field->baseline - delta >= 0)
  203.                 field->baseline -= delta;
  204.     }
  205. }
  206. /*
  207.    Preserves form contents across window resizing / backtracking.
  208.    It is assumed that FreeForms() is called before loading new
  209.    documents or reloading existing ones.
  210. */
  211. void ResizeForm(void)
  212. {
  213.     if (forms != NULL)
  214.     {
  215.         next_form = forms;
  216.         next_field = next_form->fields;
  217.         next_option = next_field->options;
  218.     }
  219. }
  220. /* ParseTable() makes 2 passes thru table data, so we need
  221.    to avoid recreating elements on 2nd pass. This procedure
  222.    should be called before pass == 1 and pass == 2 */
  223. void ProcessTableForm(int pass)
  224. {
  225.     static Form *form;
  226.     static Field *field;
  227.     static Option *option;
  228.     if (pass == 1)
  229.     {
  230.         form = next_form;
  231.         field = next_field;
  232.         option = next_option;
  233.     }
  234.     else  /* pass == 2 */
  235.     {
  236.         next_form = form;
  237.         next_field = field;
  238.         next_option = option;
  239.     }
  240. }
  241. Form *GetForm(int method, char *url, int len)
  242. {
  243.     Form *form, *last;
  244.     /* is form already defined */
  245.     if (next_form)
  246.     {
  247.         form = next_form;
  248.         next_form = form->next;
  249.         next_field = form->fields;
  250.         next_option = next_field->options;
  251.         return form;
  252.     }
  253.     form = (Form *)malloc(sizeof(Form));
  254.     form->next = NULL;
  255.     form->fields = NULL;
  256.     form->action = url; /* strdup2(url, len); --Spif */
  257.     form->alen = len;
  258.     form->method = method;
  259.     next_field = NULL;
  260.     next_option = NULL;
  261.     /* insert at end of list */
  262.     if (forms)
  263.     {
  264.         last = forms;
  265.         while (last->next)
  266.             last = last->next;
  267.         last->next = form;
  268.     }
  269.     else
  270.         forms = form;
  271.     return form;
  272. }
  273. Form *DefaultForm(void)
  274. {
  275.     return GetForm(GET, CurrentDoc->url, strlen(CurrentDoc->url));
  276. }
  277. /* font should be passed in lower 4 bits of flags */
  278. Field *GetField(Form *form, int type, int x, char *name, int nlen,
  279.                char *value, int vlen, int rows, int cols , int flags)
  280. {
  281.     int em, font;
  282.     char *s;
  283.     Field *field, *last;
  284.     if (form == NULL)
  285.         return NULL;
  286.     /* if we are resizing the form or backtracking to it then
  287.        we need to resuse the existing data structures to preserve
  288.        any chances that have been made to the default values */
  289.     
  290.     if ((field=FindField(form, type, name, nlen))== NULL)
  291.     {
  292.         if (next_field)
  293. {
  294.     field = next_field;
  295.     next_field = field->next;
  296.     next_option = field->options;
  297.     goto set_size;
  298. }
  299. field = (Field *)malloc(sizeof(Field));
  300. next_option = NULL;
  301. field->next = NULL;
  302. field->form = form;
  303. field->type = type;
  304. field->name = name;
  305. field->nlen = nlen;
  306. field->value = strndup(value, vlen);
  307. field->bufsize = vlen+1;
  308. field->buflen = vlen;    
  309. field->flags = flags;
  310. field->x = x;
  311. field->x_indent = 0;
  312. field->y_indent = 0;
  313. field->baseline = -1;
  314. field->options = 0;
  315.     /* insert at end of list */
  316. if (form->fields)
  317. {
  318.     last = form->fields;
  319.     while (last->next)
  320.         last = last->next;
  321.     last->next = field;
  322. }
  323. else
  324.     form->fields = field;
  325. if (type == TEXTFIELD) {
  326.     field->text_field = (TextField *)malloc(sizeof(TextField));
  327.     field->text_field->buffer = NULL;
  328.     field->text_field->length = 0;
  329.     field->text_field->used = 0;
  330.     field->text_field->scratch[0] = '';
  331. }
  332.     set_size:
  333. field->x = x;
  334. font = flags & 0x0F;
  335. em = WIDTH(font, "mite", 4)/4;
  336. if (type == RADIOBUTTON || type == CHECKBOX)
  337. {
  338.     field->width = ASCENT(font) + DESCENT(font) - 2;
  339.     field->height = field->width;
  340.     field->above = ASCENT(font) - 1;
  341. }
  342. else  /* TEXTFIELD and OPTIONLIST */
  343. {
  344.     if (type == SUBMITBUTTON)
  345.     {
  346.         if (vlen == 0)
  347. {
  348.     s = " Submit Query ";
  349.     vlen = strlen(s);
  350.     field->value = strdup2(s, vlen);
  351.     field->buflen = vlen;
  352.     field->bufsize = 1 + vlen;
  353. field->width = 8 + WIDTH(font, field->value, field->buflen);
  354.     }
  355.     else if (type == RESETBUTTON)
  356.     {
  357.         if (vlen == 0)
  358. {
  359.     s = " Reset ";
  360.     vlen = strlen(s);
  361.     field->value = strdup2(s, vlen);
  362.     field->buflen = vlen;
  363.     field->bufsize = 1 + vlen;
  364. field->width = 8 + WIDTH(font, field->value, field->buflen);
  365.     }
  366.     else
  367.         field->width = 8 + cols * em;
  368.     field->height = 4 + rows * SPACING(Fonts[font]);
  369.     field->above = ASCENT(font) + 3;
  370. }
  371.     }
  372.     else
  373.     {
  374.       return(field);
  375.     }
  376.     return field;
  377. }
  378. /* howcome 27/7/95: should AddOption return Option ? */
  379. void AddOption(Field *field, int flags, char *label, int len)
  380. {
  381.     int width, font;
  382.     Option *option, *last;
  383.     /* if we are resizing the form or backtracking to it then
  384.        we need to resuse the existing data structures to preserve
  385.        any chances that have been made to the default values */
  386.     if (next_option)
  387.     {
  388.         option = next_option;
  389.         next_option = option->next;
  390.         return /*option*/;
  391.     }
  392.     option = (Option *)malloc(sizeof(Option));
  393.     option->next = NULL;
  394.     option->flags = flags;
  395.     option->label = strdup(label);
  396.     font = flags & 0xF;
  397.     width = 6 + WIDTH(font, label, len) + field->height;
  398.     if (width > field->width)
  399. field->width = width;
  400.     
  401.     /* insert at end of list */
  402.     
  403.     if (field->options)
  404.     {
  405.         last = field->options;
  406. while (last->next)
  407. {
  408.     if (strlen(last->label) == len)
  409. if ( strncmp( last->label, label, len) == 0)
  410. {
  411.     if(option) /* avoid any possibility of memory leak --SPif 18/Oct/95 */
  412.     {
  413. free(option->label);
  414. free(option);
  415.     };
  416.     return /*NULL*/;
  417. }; /* don't add 2 times the same option --Spif 18-Oct-95 */
  418.             last = last->next;
  419. };
  420. if (strlen(last->label) != len)
  421.     last->next = option;
  422. else
  423.     if ( strncmp( last->label, label, len))
  424. last->next = option;
  425.     else
  426. return/* NULL*/;
  427.     }
  428.     else
  429.     {
  430.         option->flags |= CHECKED;
  431.         field->options = option;
  432.     };
  433.     field->y_indent++;
  434. }
  435. Field *CurrentRadioButton(Form *form, char *name, int nlen)
  436. {
  437.     Field *field;
  438.     if (form == NULL)
  439.         return NULL;
  440.     field = form->fields;
  441.     while (field)
  442.     {
  443.         if (strncasecmp(field->name, name, nlen) == 0 && (field->flags & CHECKED))
  444.             return field;
  445.         field = field->next;
  446.     }
  447.     return field;
  448. }
  449. void HideDropDown(GC gc, Field *field)
  450. {
  451.     int width, height, x1, y1;
  452.     height = field->height;
  453.     width = field->width - height + 2;
  454.     x1 = field->frame_indent + field->x - PixelIndent;
  455.     y1 = height + Abs2Win(field->baseline) - ASCENT(font) - 2;
  456.     DisplayHTML(x1, y1, width, 6 + field->y_indent * (height - 4));
  457.     ClipToWindow();
  458. }
  459. /* called when testing mouse down/up (event = BUTTONDOWN or BUTTONUP) */
  460. int ClickedInField(GC gc, int indent, int baseline, Field *field, int x, int y, int event)
  461. {
  462.     int y1;
  463.     Field *field_link;
  464.     if(CurrentDoc->edited_field)   /* can get rid of this (in www.c buttonpress) */
  465.     {
  466. free(CurrentDoc->edited_field->value);
  467. CurrentDoc->edited_field->value = Buffer2Str(CurrentDoc->field_editor);
  468. CurrentDoc->edited_field = NULL;
  469. FreeBuffer(CurrentDoc->field_editor);
  470. CurrentDoc->field_editor = NULL;
  471.     };
  472.     if (field->type == CHECKBOX || field->type == RADIOBUTTON)
  473.         y1 = baseline - ASCENT(font) + 2;
  474.     else if (field->type == OPTIONLIST)
  475.         y1 = baseline - ASCENT(font) - 2;
  476.     else   /* TEXTFIELD */
  477.         y1 = baseline - ASCENT(font) - 2;
  478.     x -= indent; /* fix event bug with form fields *//* howcome: applied 18/11/94 */
  479.     if (field->x <= x && x < field->x + field->width &&
  480.                 y1 <= y && y < y1 + field->height)
  481.     {
  482.         if (event == BUTTONUP)
  483.         {
  484.   TextFieldFocus = FALSE; /* howcome: will be set to true if this is a text field */
  485.             /* remove focus from current field */
  486.             if (focus && focus != field)
  487.             {
  488.                 focus->flags &= ~CHECKED;
  489.                 if (focus->type == OPTIONLIST)
  490.                     HideDropDown(gc, focus);
  491.                 else if (focus->type == TEXTFIELD)
  492.                     PaintField(gc, -1, Abs2Win(focus->baseline), focus);
  493.                 focus = NULL;
  494.             }
  495.             if (field->type == RADIOBUTTON)
  496.             {
  497.         field->flags |= CHECKED;
  498. PaintField(gc, indent, baseline, field);
  499. for( field_link=field->form->fields ; field_link!=NULL; field_link = field_link->next)
  500. {
  501.     if( field_link!= field) /* set the other buttons with the same name ;) */
  502.     {
  503.         if( (field_link->type == RADIOBUTTON) && (strncasecmp(field_link->name,field->name,field->nlen)==0))
  504.     if(field_link->flags & CHECKED)
  505.     {
  506.       field_link->flags ^= CHECKED;
  507.       if (field_link->baseline >= 0)
  508.   PaintField(gc, -1, Abs2Win(field_link->baseline), field_link);
  509.     };
  510.     };
  511. };
  512.     }
  513.             else if (field->type == CHECKBOX) 
  514.             {
  515.         field->flags ^= CHECKED;
  516.         PaintField(gc, indent, baseline, field);
  517.     }
  518.             if (field->type == OPTIONLIST)
  519.             {
  520.                 if (field->flags & CHECKED)
  521.                 {
  522.                     field->flags &= ~CHECKED;
  523.                     HideDropDown(gc, field);
  524.                 }
  525.                 else
  526.                 {
  527.                     field->flags |= CHECKED;
  528.                     PaintDropDown(gc, field, indent);
  529.                     focus = field;
  530.                 }
  531.             }
  532.             else if ((field->type == TEXTFIELD) ||(field->type == PASSWD))
  533.             {
  534.                 field->flags |= CHECKED;
  535.                 PaintField(gc, indent, baseline, field);
  536.                 focus = field;
  537. CurrentDoc->edited_field = field;
  538. CurrentDoc->field_editor = Str2Buffer(field->value);
  539. PaintFieldCursorBuffer(gc, strikeColor, CurrentDoc->field_editor, field);
  540. /* howcome started playing 19/1/95 */
  541. TextFieldFocus = TRUE;
  542. if (OpenURL|Authorize|FindStr) {
  543.     OpenURL = Authorize = FindStr = 0;
  544.     DisplayUrl();
  545. }
  546.             }
  547.         }
  548.         return 1;
  549.     }
  550.     return 0;
  551. }
  552. /* set clip rectangle to intersection with displayRect
  553.    to clip text strings in text fields */
  554. int ClipIntersection(GC gc, int x, int y, unsigned int width, unsigned int height)
  555. {
  556.     int xl, yl, xm, ym;
  557.     XRectangle rect;
  558.     xl = x;
  559.     xm = x + width;
  560.     yl = y;
  561.     ym = y + height;
  562.     if (xl < displayRect.x)
  563.         xl = displayRect.x;
  564.     if (yl < displayRect.y)
  565.         yl = displayRect.y;
  566.     if (xm > displayRect.x + displayRect.width)
  567.         xm = displayRect.x + displayRect.width;
  568.     if (ym > displayRect.y + displayRect.height)
  569.         ym = displayRect.y + displayRect.height;
  570.     if (xm > xl && ym > yl)
  571.     {
  572.         rect.x = xl;
  573.         rect.y = yl;
  574.         rect.width = xm - xl;
  575.         rect.height = ym - yl;
  576.         XSetClipRectangles(display, gc, 0, 0, &rect, 1, Unsorted);
  577.     }
  578.     return 0;
  579. }
  580. int ClickedInDropDown(GC gc, Field *field, int indent, int event, int x, int y)
  581. {
  582.     int font, baseline, bw, bh, dh, x1, y1, n;
  583.     Option *option;
  584.     font = field->flags & 0x0F;
  585.    
  586.     baseline = Abs2Win(field->baseline);
  587.     bw = field->width - field->height + 2;
  588.     bh = 6 + field->y_indent * (field->height - 4);
  589.     dh = field->height;
  590.     x1 = field->frame_indent + field->x - PixelIndent;
  591.     y1 = field->height + baseline - ASCENT(font) - 2;
  592.     n = field->x_indent;
  593.     if (x1 + 2 < x && x < x1 + bw - 2 && y1 + 2 < y && y < y1 + bh)
  594.     {
  595.         if (event == BUTTONDOWN)
  596.             return 1;
  597.         if ( !(field->flags & MULTIPLE) )
  598.         {
  599.             for (option = field->options; option; option = option->next)
  600.         if((option->flags & CHECKED) == CHECKED)
  601.   option->flags ^= CHECKED;
  602. }
  603.         n = ((y - y1) * field->y_indent) / bh;
  604.         field->x_indent = n;
  605.         option = field->options;
  606.         while (n-- > 0){
  607.             option = option->next;
  608.   };
  609.         if (option->flags & CHECKED)
  610.         {
  611.             option->flags ^= CHECKED;
  612.             for (option = field->options; option; option = option->next)
  613.             {
  614.                 if (option->flags & CHECKED)
  615.                     break;
  616.             }
  617.         }
  618.         else
  619.             option->flags |= CHECKED;
  620.         if ( !(field->flags & MULTIPLE) )
  621.     field->flags &= ~CHECKED;
  622.     
  623.         Free(field->value);
  624.         field->value = (option ? strdup(option->label) : "");
  625.         ClipToWindow();
  626.         PaintField(gc, -1, Abs2Win(focus->baseline), field);
  627.         if (field->flags & MULTIPLE)
  628.             PaintDropDown(gc, field, indent);
  629.         else
  630.             HideDropDown(gc, field);
  631.         return 1;
  632.     }
  633.     return 0;
  634. }
  635. void PaintDropDown(GC gc, Field *field, int indent)
  636. {
  637.     int font, baseline, width, height, h, x1, y1, y2, n, i;
  638.     Option *option;
  639.     /* nasty kludge !!!! */
  640.     if (indent < 0)
  641.         indent = field->frame_indent;
  642.     baseline = Abs2Win(field->baseline);
  643.     font = field->flags & 0x0F;
  644.     SetFont(gc, font);
  645.     height = field->height;
  646.     width = field->width - height + 2;
  647.     x1 = indent + field->x - PixelIndent;
  648.     y1 = height + baseline - ASCENT(font) - 2;
  649.     n = field->x_indent;
  650.     h = 6 + field->y_indent * (height - 4);
  651.     y2 = baseline + height;
  652.     option = field->options;
  653.     XSetForeground(display, gc, windowColor);
  654.     XFillRectangle(display, win, gc, x1, y1, width, h);
  655.     DrawOutSet(win, gc, x1, y1, width, h);
  656.     y1 += 2;
  657.     for (option = field->options, i = 0; option; option = option->next)
  658.     {
  659.         if (option->flags & CHECKED)
  660.         {
  661.             XSetForeground(display, gc, statusColor);
  662.             XFillRectangle(display, win, gc, x1+2, y1, width-4, height-2);
  663.         }
  664.         XSetForeground(display, gc, textColor);
  665.         XDrawString(display, win, gc, x1+4, y2, option->label, strlen(option->label));
  666.         y2 += height - 4;
  667.         y1 += height - 4;
  668.         ++i;
  669.     }
  670. }
  671. void PaintTickMark(GC gc, int x, int y, unsigned int w, unsigned int h)
  672. {
  673.     int x1, y1, x2, y2, x3, y3;
  674.     x1 = x;
  675.     x2 = x + w/3;
  676.     x3 = x + w-1;
  677.     y1 = y + h - h/3 - 1;
  678.     y2 = y + h - 1;
  679.     y3 = y;
  680.     XSetForeground(display, gc, textColor);
  681.     XDrawLine(display, win, gc, x1, y1, x2, y2);
  682.     XDrawLine(display, win, gc, x2, y2, x3, y3);
  683. }
  684. void PaintCross(GC gc, int x, int y, unsigned int w, unsigned int h)
  685. {
  686.     XSetForeground(display, gc, strikeColor);
  687.     XDrawLine(display, win, gc, x, y, x+w, y+w);
  688.     XDrawLine(display, win, gc, x, y+w, x+w, y);
  689.     XSetForeground(display, gc, textColor);
  690. }
  691. void PaintField(GC gc, int indent, int baseline, Field *field)
  692. {
  693.     char *s,*pos,*dump;
  694.     int font, active, width, height, x1, y1, y2, r;
  695.     Option *option;
  696.     active = field->flags & CHECKED;
  697.     font = field->flags & 0x0F;
  698.     width = field->width;
  699.     height = field->height;
  700.  /* cache absolute position of baseline */
  701.     field->baseline = Win2Abs(baseline);
  702.     /* kludge for fields in different frames */
  703.     if (indent >= 0)
  704.         field->frame_indent = indent;
  705.     else
  706.         indent = field->frame_indent;
  707.     if (field->type == TEXTFIELD)
  708.     {
  709.         x1 = indent + field->x - PixelIndent - field->x_indent;
  710.         y2 = baseline - ASCENT(font) - 2;
  711.         ClipIntersection(gc, x1, y2, width, height);
  712.         XSetForeground(display, gc, (active ? statusColor : windowColor));
  713.         XFillRectangle(display, win, gc, x1, y2, width, height);
  714.         DrawInSet(win, gc, x1, y2, width, height);
  715.         ClipIntersection(gc, x1+2, y2, width-4, height);
  716.         if (field->buflen > 0)
  717.         {
  718.     dump = (char *)malloc(strlen(field->value)+1);
  719.     strncpy(dump,field->value, field->buflen);
  720.     *(dump+field->buflen)=0;
  721.     pos = dump;
  722.     while(*pos)
  723. if(*pos=='n')
  724.     *pos++=0;
  725. else
  726.     pos++;
  727.     pos = dump;
  728.     while(pos-dump<field->buflen)
  729.     {
  730. y1 = y2 + ASCENT(font) + 2;
  731. SetFont(gc, font);
  732. XSetForeground(display, gc, textColor);
  733. XDrawString(display, win, gc, x1+4, y1, pos, strlen(pos));
  734. y2 += ASCENT(font)+4;
  735. pos += strlen(pos)+1;
  736.     };
  737.     free(dump);
  738.         }
  739.         XSetForeground(display, gc, textColor);
  740.         XSetClipRectangles(display, gc, 0, 0, &displayRect, 1, Unsorted);
  741.     }
  742.     else if (field->type == PASSWD)
  743.     {
  744.         x1 = indent + field->x - PixelIndent - field->x_indent;
  745.         y2 = baseline - ASCENT(font) - 2;
  746.         ClipIntersection(gc, x1, y2, width, height);
  747.         XSetForeground(display, gc, (active ? statusColor : windowColor));
  748.         XFillRectangle(display, win, gc, x1, y2, width, height);
  749.         DrawInSet(win, gc, x1, y2, width, height);
  750.         ClipIntersection(gc, x1+2, y2, width-4, height);
  751.         if (field->buflen > 0)
  752.         {
  753.     int loop_i;
  754.     dump = (char *)malloc(strlen(field->value)+1);
  755.     for(loop_i=0;loop_i<field->buflen;loop_i++)
  756. dump[loop_i] = '*';
  757.     *(dump+field->buflen)=0;
  758.     pos = dump;
  759.     while(*pos)
  760. if(*pos=='n')
  761.     *pos++=0;
  762. else
  763.     pos++;
  764.     pos = dump;
  765.     while(pos-dump<field->buflen)
  766.     {
  767. y1 = y2 + ASCENT(font) + 2;
  768. SetFont(gc, font);
  769. XSetForeground(display, gc, textColor);
  770. XDrawString(display, win, gc, x1+4, y1, pos, strlen(pos));
  771. y2 += ASCENT(font)+4;
  772. pos += strlen(pos)+1;
  773.     };
  774.     free(dump);
  775.         }
  776.         XSetForeground(display, gc, textColor);
  777.         XSetClipRectangles(display, gc, 0, 0, &displayRect, 1, Unsorted);
  778.     }
  779.     else if (field->type == SUBMITBUTTON || field->type == RESETBUTTON)
  780.     {
  781. char *the_string = NULL;
  782. int i, j, k, len, ok;
  783. s = field->value;
  784. if (field->buflen > 0)
  785.         {
  786.     s = field->value;
  787.     the_string = (char *)calloc(strlen(s)+1, sizeof(char));
  788.     len = strlen(s);
  789.     for(i=k=0; i<len; i++,k++)
  790. if(s[i] == '&')
  791. {
  792.     for(ok= FALSE,j=i; !ok && j< len; j++)
  793. ok = ((s[j]==';') || (s[j]==' ')); 
  794.     the_string[k] = entity(s+i+1, &j);
  795.     i += j - 1;
  796. }
  797. else
  798.     the_string[k] = s[i];
  799.     field->width = 8 + WIDTH(font, the_string, strlen(the_string));
  800.     width = field->width;     
  801. };
  802.         x1 = indent + field->x - PixelIndent - field->x_indent;
  803.         y2 = baseline - ASCENT(font) - 2;
  804.         ClipIntersection(gc, x1, y2, width, height);
  805.         XSetForeground(display, gc, windowColor);
  806.         XFillRectangle(display, win, gc, x1, y2, width, height);
  807.         DrawOutSet(win, gc, x1, y2, width, height);
  808.         ClipIntersection(gc, x1+2, y2, width-4, height);
  809.         
  810.         if (field->buflen > 0)
  811.         {
  812.     y1 = y2 + ASCENT(font) + 2;
  813.             SetFont(gc, font);
  814.             XSetForeground(display, gc, textColor);
  815.             XDrawString(display, win, gc, x1+4, y1, the_string, strlen(the_string));
  816.     free(the_string);
  817.         }
  818.         XSetForeground(display, gc, textColor);
  819.         XSetClipRectangles(display, gc, 0, 0, &displayRect, 1, Unsorted);
  820.     }
  821.     else if (field->type == OPTIONLIST)
  822.     {
  823.         x1 = indent + field->x - PixelIndent;
  824.         y2 = baseline - ASCENT(font) - 2;
  825.         XSetForeground(display, gc, windowColor);
  826.         XFillRectangle(display, win, gc, x1, y2, width, height);
  827.         DrawOutSet(win, gc, x1, y2, width, height);
  828.         if (field->flags & MULTIPLE)
  829.         {
  830.             DrawOutSet(win, gc, x1+3+width-height, y2 - 2 + height/3, height-7, 6);
  831.             DrawOutSet(win, gc, x1+3+width-height, y2 - 3 + 2*height/3, height-7, 6);
  832.         }
  833.         else /* single choice menu drawn with one bar */
  834.         {
  835.             DrawOutSet(win, gc, x1+3+width-height, y2 - 3 + height/2, height-7, 6);
  836.             if (*(field->value) == '' && field->options != NULL)
  837.             {
  838.                 field->x_indent = 0;
  839.                 option = field->options;
  840.                 option->flags |= CHECKED;
  841.                 Free(field->value);
  842.                 field->value = strdup(option->label);
  843.             }
  844.         }
  845.         if (field->y_indent > 0 && field->value)
  846.         {
  847.             y1 = y2 + ASCENT(font) + 2;
  848.             SetFont(gc, font);
  849.             XSetForeground(display, gc, textColor);
  850.             XDrawString(display, win, gc, x1+4, y1, field->value, strlen(field->value));
  851.         }
  852.         XSetForeground(display, gc, textColor);
  853.     }
  854.     else if (field->type == CHECKBOX)
  855.     {
  856.         x1 = indent + field->x - PixelIndent;
  857.         y2 = baseline-ASCENT(font) + 2;
  858.         XSetForeground(display, gc, (active ? statusColor : windowColor));
  859.         XFillRectangle(display, win, gc, x1, y2, width, width);
  860.         if (active)
  861.         {
  862.             PaintTickMark(gc, x1+3, y2+3, width-6, width-7);
  863. #if 0
  864.             XSetForeground(display, gc, windowBottomShadow);
  865.             XFillRectangle(display, win, gc, x1+3, y2+3, width-6, width-6);
  866. #endif
  867.             DrawInSet(win, gc, x1, y2, width, width);
  868.         }
  869.         else
  870.             DrawOutSet(win, gc, x1, y2, width, width);
  871.         XSetForeground(display, gc, textColor);
  872.     }
  873.     else if (field->type == RADIOBUTTON)
  874.     {
  875.         x1 = indent + field->x - PixelIndent;
  876.         y2 = baseline-ASCENT(font)+2;
  877.         XSetForeground(display, gc, (active ? statusColor : windowColor));
  878.         XFillArc(display, win, gc, x1, y2, width, width, 0, 360<<6);
  879.         if (active)
  880.         {
  881.             r = width/4;
  882.             DrawInSetCircle(gc, x1, y2, width, width);
  883.             XSetForeground(display, gc, windowBottomShadow);
  884.             width -= r+r;
  885.             XFillArc(display, win, gc, x1+r, y2+r, width, width, 0, 360<<6);
  886.         }
  887.         else
  888.             DrawOutSetCircle(gc, x1, y2, width, width);
  889.         XSetForeground(display, gc, textColor);
  890.     }
  891. }
  892. /* use this routine to hide/show cursor by
  893.    using color = windowShadow/textColor respectively */
  894. void PaintPopupField(Window popwin,GC gc, int indent, int baseline, Field *field)
  895. {
  896.     char *pos,*dump;
  897.     int font, active, width, height, x1, y1, y2;
  898.  
  899.     active = field->flags & CHECKED;
  900.     font = field->flags & 0x0F;
  901.     width = field->width;
  902.     height = field->height;
  903.     field->baseline = baseline;
  904.     /* kludge for fields in different frames */
  905.     if (indent >= 0)
  906.         field->frame_indent = indent;
  907.     else
  908.         indent = field->frame_indent;
  909.     if (field->type == TEXTFIELD)
  910.     {
  911.         x1 = indent + field->x - field->x_indent;
  912.         y2 = baseline - ASCENT(font) - 2;
  913. /*        ClipIntersection(gc, x1, y2, width, height); */
  914.         XSetForeground(display, gc, (active ? statusColor : windowColor));
  915.         XFillRectangle(display, popwin, gc, x1, y2, width, height);
  916.         DrawInSet(popwin, gc, x1, y2, width, height);
  917. /*        ClipIntersection(gc, x1+2, y2, width-4, height);*/
  918.         if (field->buflen > 0)
  919.         {
  920.     dump = (char *)malloc(strlen(field->value)+1);
  921.     strncpy(dump,field->value, field->buflen);
  922.     *(dump+field->buflen)=0;
  923.     pos = dump;
  924.     while(*pos)
  925. if(*pos=='n')
  926.     *pos++=0;
  927. else
  928.     pos++;
  929.     pos = dump;
  930.     while(pos-dump<field->buflen)
  931.     {
  932. y1 = y2 + ASCENT(font) + 2;
  933. SetFont(gc, font);
  934. XSetForeground(display, gc, textColor);
  935. XDrawString(display, popwin, gc, x1+4, y1, pos, strlen(pos));
  936. y2 += ASCENT(font)+4;
  937. pos += strlen(pos)+1;
  938.     };
  939.     free(dump);
  940.         }
  941.         XSetForeground(display, gc, textColor);
  942. /*  XSetClipRectangles(display, gc, 0, 0, &displayRect, 1, Unsorted);*/
  943.     }
  944.     else if (field->type == PASSWD)
  945.     {
  946.         x1 = indent + field->x - field->x_indent;
  947.         y2 = baseline - ASCENT(font) - 2;
  948. /*     ClipIntersection(gc, x1, y2, width, height);*/
  949.         XSetForeground(display, gc, (active ? statusColor : windowColor));
  950.         XFillRectangle(display, popwin, gc, x1, y2, width, height);
  951.         DrawInSet(popwin, gc, x1, y2, width, height);
  952. /*       ClipIntersection(gc, x1+2, y2, width-4, height);*/
  953.         if (field->buflen > 0)
  954.         {
  955.     int loop_i;
  956.     dump = (char *)malloc(strlen(field->value)+1);
  957.     for(loop_i=0;loop_i<field->buflen;loop_i++)
  958. dump[loop_i] = '*';
  959.     *(dump+field->buflen)=0;
  960.     pos = dump;
  961.     while(*pos)
  962. if(*pos=='n')
  963.     *pos++=0;
  964. else
  965.     pos++;
  966.     pos = dump;
  967.     while(pos-dump<field->buflen)
  968.     {
  969. y1 = y2 + ASCENT(font) + 2;
  970. SetFont(gc, font);
  971. XSetForeground(display, gc, textColor);
  972. XDrawString(display, popwin, gc, x1+4, y1, pos, strlen(pos));
  973. y2 += ASCENT(font)+4;
  974. pos += strlen(pos)+1;
  975.     };
  976.     free(dump);
  977.         }
  978.         XSetForeground(display, gc, textColor);
  979. /*    XSetClipRectangles(display, gc, 0, 0, &displayRect, 1, Unsorted);*/
  980.     }
  981. }
  982. void PaintCursor(Window win, GC gc,  int indent, int baseline ,Field *field, int pos)
  983. {
  984.     int font, active, width, height, x1, y2, r;
  985.     
  986.     active = field->flags & CHECKED;
  987.     font = field->flags & 0x0F;
  988.     width = field->width;
  989.     height = field->height;
  990.     field->baseline = baseline;
  991.     /* kludge for fields in different frames */
  992.     if (indent >= 0)
  993.         field->frame_indent = indent;
  994.     else
  995.         indent = field->frame_indent;
  996.     if (pos > 0)
  997.         r = WIDTH(font, field->value, pos);
  998.     else
  999.         r = 0;
  1000.     x1 = indent + field->x - field->x_indent;
  1001.     y2 = baseline - ASCENT(font) - 2;
  1002.     XSetForeground(display, gc, strikeColor);
  1003.     XFillRectangle(display, win, gc, x1 + ((r)?4:2) + r, y2+2, 1,ASCENT(font)+2);
  1004.     XSetForeground(display, gc, textColor);
  1005. }
  1006. void PaintFieldCursor(GC gc, unsigned long color)
  1007. {
  1008.     int font, width, height, x1, y2, r;
  1009.     font = focus->flags & 0x0F;
  1010.     width = focus->width;
  1011.     height = focus->height;
  1012.     x1 = focus->x - PixelIndent - focus->x_indent;
  1013.     y2 = focus->baseline - ASCENT(font) - 2;
  1014.     if (focus->buflen > 0)
  1015.         r = WIDTH(font, focus->value, cursorpos);
  1016.     else
  1017.         r = 0;
  1018.     XSetForeground(display, gc, color);
  1019.     XFillRectangle(display, win, gc, x1 + 3 + r, y2+2, 1, height-4);
  1020. }
  1021. /*
  1022.    Repair a given area of a field - called by ScrollField()
  1023.    also useful when typing a char into field
  1024. */
  1025. void RepairField(GC gc, int start, int width)
  1026. {
  1027.     int font, height, x1, y1, y2, r;
  1028.     XRectangle rect;
  1029.     font = focus->flags & 0x0F;
  1030.     width = focus->width;
  1031.     height = focus->height;
  1032.     x1 = focus->x - PixelIndent - focus->x_indent;
  1033.     rect.x = start;
  1034.     rect.y = focus->baseline - ASCENT(font);
  1035.     rect.width = width;
  1036.     rect.height = focus->height - 4;
  1037.     XSetClipRectangles(display, gc, 0, 0, &rect, 1, Unsorted);
  1038.     y2 = focus->baseline - ASCENT(font) - 2;
  1039.     XSetForeground(display, gc, statusColor);
  1040.     XFillRectangle(display, win, gc, x1, y2, width, height);
  1041.     if (focus->buflen > 0)
  1042.     {
  1043.         y1 = y2 + ASCENT(font) + 2;
  1044.         SetFont(gc, font);
  1045.         XSetForeground(display, gc, textColor);
  1046.         XDrawString(display, win, gc, x1+4, y1, focus->value, focus->buflen);
  1047.     }
  1048.     if (focus->buflen > 0)
  1049.         r = WIDTH(font, focus->value, cursorpos);
  1050.     else
  1051. r = 0;
  1052.     XSetForeground(display, gc, strikeColor);
  1053.     XFillRectangle(display, win, gc, x1 + 3 + r, y2+2, 1, height-4);
  1054.     rect.x = focus->x + 2;
  1055.     rect.y = focus->baseline - ASCENT(font);
  1056.     rect.width = focus->width - 4;
  1057.     rect.height = focus->height - 4;
  1058.     XSetClipRectangles(display, gc, 0, 0, &rect, 1, Unsorted);
  1059. }
  1060. /*
  1061.    Text field lies in rectangle box, scroll it horizontally
  1062.    by delta pixels and repair exposed area. When scrolling to left
  1063.    restrict scroll area to right of "start"
  1064.    delta is greater than zero for right scrolls
  1065.    and less than zero for left scrolls
  1066.    Useful for backspace, del char, and cursor motion
  1067.    at extreme limits of field
  1068. */
  1069. void ScrollField(GC gc, int toleft, int start, int delta)
  1070. {
  1071.     XRectangle rect;
  1072.     int width;
  1073.     rect.x  = focus->x + 2;
  1074.     rect.y = focus->baseline - ASCENT(font);
  1075.     rect.width = focus->width - 4;
  1076.     rect.height = focus->height - 4;
  1077.     XSetClipRectangles(display, gc, 0, 0, &rect, 1, Unsorted);
  1078.     if (delta < 0)  /* scroll left: delta < 0 */
  1079.     {
  1080.         if (start <= rect.x)
  1081.         {
  1082.             XCopyArea(display, win, win, gc,
  1083.                     rect.x - delta, rect.y,
  1084.                     rect.width + delta, rect.y,
  1085.                     rect.x, rect.y);
  1086.             RepairField(gc, rect.x + rect.width + delta, -delta);
  1087.         }
  1088.         else if (start < rect.x + rect.width /* width */) /* 12-Mar-96 herman@htbrug.hobby.nl */
  1089.         {
  1090.             width = rect.width + rect.x - start + delta;
  1091.             XCopyArea(display, win, win, gc,
  1092.                     start - delta, rect.y,
  1093.                     width, rect.y,
  1094.                     rect.x, rect.y);
  1095.             RepairField(gc, start + width, -delta);
  1096.         }
  1097.     }
  1098.     else  /* scroll right: delta is > 0 */
  1099.     {
  1100.         if (delta < rect.width)
  1101.         {
  1102.             XCopyArea(display, win, win, gc,
  1103.                     rect.x, rect.y,
  1104.                     rect.width - delta, rect.y,
  1105.                     rect.x + delta, rect.y);
  1106.             RepairField(gc, rect.x, delta);
  1107.         }
  1108.     }
  1109. }
  1110. char *WWWEncode(char *raw)
  1111. {
  1112.     int i,rlen;
  1113.     char *encoded,*j;
  1114.     
  1115.     rlen = strlen(raw);
  1116.     encoded=(char *)malloc(3*rlen+1); /* max size = size*3 */
  1117.     j=encoded;
  1118.     for(i=0;i<rlen;i++)
  1119.     {
  1120. if( *(raw+i) ==' ')
  1121.     *j++ = '+';       
  1122. else if ((*(raw+i) == '-')||(*(raw+i) == '_'))
  1123.     *j++=*(raw+i);
  1124. else if ((*(raw+i) < '0' ) || ((*(raw+i)<'A')&&(*(raw+i)>'9'))){
  1125.     *j++ = '%';
  1126.     sprintf(j,"%X",*(raw+i));
  1127.     j+=(*(raw+i)<16)? 1 :2;
  1128. } else if ((*(raw+i) > 'z') || ((*(raw+i)<'a')&&(*(raw+i)>'Z'))){
  1129.     *j++ = '%';
  1130.     sprintf(j,"%X",*(raw+i));
  1131.     j+=2;
  1132. } else 
  1133.     *j++=*(raw+i);
  1134.     };
  1135.     *j=0;
  1136.     j = (char *)malloc(strlen(encoded)+1);
  1137.     strcpy(j, encoded); /* we copy the string again to save the extra space allocated */
  1138.     free(encoded);
  1139.     return (j);
  1140. }
  1141. void SubmitForm(Form *form, int method, char *action, int alen, int type,
  1142.  char *name, int nlen, char *value, int vlen, Image *image,int dx, int dy, char *bufpos)
  1143. {
  1144.     char *query,*encoded,*encode_buffer;
  1145.     EditorBuffer *buffer;
  1146.     char itoabuff[32];
  1147.     Field *field,*field_link;
  1148.     Option *option;
  1149.     int first,size;
  1150.     buffer = CreateBuffer();
  1151.     first = (method == GET);
  1152.     if (image != NULL)
  1153.     {
  1154. if(first)
  1155.     AppendChar(buffer,'?');
  1156. AppendnChar(buffer, name, nlen);
  1157. AppendString(buffer, ".x=");
  1158. sprintf(itoabuff,"%d&", dx);
  1159. AppendString(buffer, itoabuff);
  1160. AppendnChar(buffer, name, nlen);
  1161. AppendString(buffer,".y=");
  1162. sprintf(itoabuff,"%d",dy);
  1163. AppendString(buffer,itoabuff);
  1164. field = FindField(form,type,name,nlen);
  1165. first = 0;
  1166.     }
  1167.     else
  1168.     {
  1169. if(nlen)
  1170.     if(vlen)
  1171.     {
  1172. if(first)
  1173.     AppendChar(buffer,'?');
  1174. AppendnChar(buffer,name,nlen);
  1175. AppendChar(buffer,'=');
  1176. encode_buffer = (char *)calloc( vlen+1, sizeof(char));
  1177. strncpy(encode_buffer,value,vlen);
  1178. *(encode_buffer+vlen)=0;
  1179. encoded = WWWEncode(encode_buffer);
  1180. AppendString(buffer,encoded); /* thanks to Marc Salomon <marc@ckm.ucsf.edu> */
  1181. free(encode_buffer);
  1182. free(encoded);
  1183. field = FindField(form,type,name,nlen);
  1184. first = 0;
  1185.     }
  1186.     else
  1187.     {
  1188. if(first)
  1189.     AppendChar(buffer,'?');
  1190. AppendnChar(buffer,name,nlen);
  1191. AppendString(buffer,"=Submit+Query");
  1192. field = FindField(form,type,name,nlen);
  1193. first = 0;
  1194.     }
  1195. else
  1196. {
  1197.     first = (method == GET) ? 1 : 2;
  1198.     field = FindField(form,type,bufpos,7);
  1199. }
  1200.     };
  1201.     for( field_link=form->fields ; field_link!=NULL; field_link = field_link->next)
  1202.     {
  1203. if( field_link!= field)
  1204. {
  1205.     switch (field_link->type)
  1206.     {
  1207.     case SUBMITBUTTON:
  1208.     case RESETBUTTON:
  1209. break;
  1210.     case RADIOBUTTON:
  1211. if(!(field_link->flags & CHECKED))
  1212.     break;
  1213.     case HIDDEN:
  1214.     case TEXTFIELD:
  1215. if(first)
  1216. {
  1217.     if(first == 1)
  1218. AppendChar(buffer,'?');
  1219.     first=0;
  1220. }
  1221. else
  1222.     AppendChar(buffer,'&');
  1223. encode_buffer = (char *) calloc( field_link->nlen+1, sizeof(char));
  1224. strncpy(encode_buffer, field_link->name, field_link->nlen);
  1225. *(encode_buffer+field_link->nlen)=0;
  1226. encoded = WWWEncode(encode_buffer);
  1227. AppendString(buffer, encoded);
  1228. free(encoded);
  1229. free(encode_buffer);
  1230. AppendChar(buffer, '=');
  1231. encode_buffer = (char *) calloc( field_link->buflen+1, sizeof(char));
  1232. strncpy(encode_buffer,field_link->value,field_link->buflen);
  1233. *(encode_buffer+field_link->buflen)=0;
  1234. encoded = WWWEncode(encode_buffer);
  1235. AppendString(buffer, encoded);
  1236. free(encoded);
  1237. free(encode_buffer);
  1238. break;
  1239.     case CHECKBOX:
  1240. if(field_link->flags & CHECKED)
  1241. {
  1242.     if(first)
  1243.     {
  1244. if(first == 1)
  1245.     AppendChar(buffer,'?');
  1246. first = 0;
  1247.     }
  1248.     else
  1249. AppendChar(buffer,'&');
  1250.     encode_buffer = (char *) calloc( field_link->nlen+1, sizeof(char));
  1251.     strncpy(encode_buffer, field_link->name, field_link->nlen);
  1252.     *(encode_buffer+field_link->nlen)=0;
  1253.     encoded = WWWEncode(encode_buffer);
  1254.     AppendString(buffer, encoded);
  1255.     free(encoded);
  1256.     free(encode_buffer);
  1257.     AppendString(buffer, "=on");
  1258. };
  1259. break; 
  1260.     case OPTIONLIST:
  1261. if(field_link->flags & MULTIPLE)
  1262. {
  1263.     for (option = field_link->options; option; option = option->next)
  1264.     {
  1265. if((option->flags & CHECKED) == CHECKED)
  1266. {
  1267.     if(first)
  1268.     {
  1269. if(first == 1)
  1270.     AppendChar(buffer,'?');
  1271. first = 0;
  1272.     }
  1273.     else
  1274. AppendChar(buffer,'&');
  1275.     
  1276.     encode_buffer = (char *) calloc( field_link->nlen+1, sizeof(char));
  1277.     strncpy(encode_buffer, field_link->name, field_link->nlen);
  1278.     *(encode_buffer+field_link->nlen)=0;
  1279.     encoded = WWWEncode(encode_buffer);
  1280.     AppendString(buffer, encoded);
  1281.     free(encoded);
  1282.     free(encode_buffer);
  1283.     AppendChar(buffer, '=');
  1284.     size = strlen(option->label);
  1285.     if(size)
  1286. if(field_link->value[size-1]==' ')
  1287.     field_link->value[size-1]=0;  /* "eat" the last blank */
  1288.     encode_buffer = (char *) calloc( strlen(option->label)+1, sizeof(char));
  1289.     strcpy(encode_buffer,option->label);
  1290.     encoded = WWWEncode(encode_buffer);
  1291.     AppendString(buffer, encoded);
  1292.     free(encoded);
  1293.     free(encode_buffer);
  1294. };
  1295.     }
  1296. }
  1297. else
  1298. {
  1299.     if(first)
  1300.     {
  1301. if(first == 1)
  1302.     AppendChar(buffer,'?');
  1303. first = 0;
  1304.     }
  1305.     else
  1306. AppendChar(buffer,'&');
  1307.     
  1308.     encode_buffer = (char *) calloc( field_link->nlen+1, sizeof(char));
  1309.     strncpy(encode_buffer, field_link->name, field_link->nlen);
  1310.     *(encode_buffer+field_link->nlen)=0;
  1311.     encoded = WWWEncode(encode_buffer);
  1312.     AppendString(buffer, encoded);
  1313.     free(encoded);
  1314.     free(encode_buffer);
  1315.     AppendChar(buffer, '=');
  1316.     size = strlen(field_link->value);
  1317.     if(size)
  1318. if(field_link->value[size-1]==' ')
  1319.     field_link->value[size-1]=0;  /* "eat" the last blank */
  1320.     encode_buffer = (char *) calloc( strlen(field_link->value)+1, sizeof(char));
  1321.     strcpy(encode_buffer,field_link->value);
  1322.     encoded = WWWEncode(encode_buffer);
  1323.     AppendString(buffer, encoded);
  1324.     free(encoded);
  1325.     free(encode_buffer);
  1326. };
  1327. break;
  1328.     };
  1329. };
  1330.     }
  1331.     switch(method)
  1332.     {
  1333.     case GET:
  1334. if(action)
  1335.     InsertnChar(buffer,0,action,alen);
  1336. else
  1337.     InsertString(buffer,0,CurrentDoc->href);
  1338. query = Buffer2Str(buffer);
  1339. /* printf("fetching |%s|n",query); */
  1340. OpenDoc(query);
  1341. break;
  1342.     case POST:
  1343. encoded = Buffer2Str(buffer);
  1344. query = (char *) calloc(alen+1, sizeof(char));
  1345. strncpy(query, action, alen);
  1346. *(query+alen)=0;
  1347. PostDoc(query, encoded); 
  1348. /* printf("posting [%s][%s]n",query,encoded); */
  1349. break;
  1350.     };
  1351. }
  1352. void PaintFieldCursorBuffer(GC gc, unsigned long color, EditorBuffer *buffer, Field *field)
  1353. {
  1354.     int font, width, height, x1, y2, r;
  1355.     int numline;
  1356.     int numcol;
  1357.     font = field->flags & 0x0F;
  1358.     numline = LineNumber(buffer);
  1359.     width = field->width;
  1360.     height = field->height;
  1361.     x1 = field->x - PixelIndent - field->x_indent ;
  1362.     y2 = Abs2Win(field->baseline) + (numline-1)*(ASCENT(font)+4);
  1363.     ClipIntersection(gc, x1+2, Abs2Win(field->baseline) - ASCENT(font) - 4, width-4, height);
  1364.     numcol = ColNumber(buffer);
  1365.     if (buffer->size > 0)
  1366.         r = WIDTH(font, field->value + buffer->pos - numcol, numcol);
  1367.     else
  1368.         r = 0;
  1369.     
  1370.     XSetForeground(display, gc, color);
  1371.     XFillRectangle(display, win, gc, x1 + 7 + r, y2+4, 1,ASCENT(font)+4);
  1372.     XSetForeground(display, gc, textColor);
  1373.     XSetClipRectangles(display, gc, 0, 0, &displayRect, 1, Unsorted);
  1374. }
  1375. #if 0
  1376. void PaintFieldEditor(GC gc, int indent, int baseline, Field *field) /* to display editor --Spif 28-Nov-95 */
  1377. {
  1378.     char *s,*pos,*dump;
  1379.     int font, active, width, height, x1, y1, y2, r;
  1380.     Option *option;
  1381.     
  1382.     active = field->flags & CHECKED;
  1383.     font = field->flags & 0x0F;
  1384.     
  1385.     width = field->width;
  1386.     height = field->height;
  1387.     
  1388.     /* cache absolute position of baseline */
  1389.     field->baseline = Win2Abs(baseline);
  1390.     /* kludge for fields in different frames */
  1391.     if (indent >= 0)
  1392.         field->frame_indent = indent;
  1393.     else
  1394.         indent = field->frame_indent;
  1395.     if (field->type == TEXTFIELD)
  1396.     {
  1397.         x1 = indent + field->x - PixelIndent - field->x_indent;
  1398.         y2 = baseline - ASCENT(font) - 2;
  1399.         ClipIntersection(gc, x1, y2, width, height);
  1400.         XSetForeground(display, gc, (active ? statusColor : windowColor));
  1401.         XFillRectangle(display, win, gc, x1, y2, width, height);
  1402.         DrawInSet(win, gc, x1, y2, width, height);
  1403.         ClipIntersection(gc, x1+2, y2, width-4, height);
  1404.         if (field->buflen > 0)
  1405.         {
  1406.     dump = (char *)malloc(strlen(field->value)+1);
  1407.     strcpy(dump,field->value);
  1408.     pos = dump;
  1409.     while(*pos)
  1410. if(*pos=='n')
  1411.     *pos++=0;
  1412. else
  1413.     pos++;
  1414.     pos = dump;
  1415.     while(pos-dump<field->buflen)
  1416.     {
  1417. printf("[%s]n",pos);
  1418. y1 = y2 + ASCENT(font) + 2;
  1419. SetFont(gc, font);
  1420. XSetForeground(display, gc, textColor);
  1421. XDrawString(display, win, gc, x1+4, y1, pos, strlen(pos));
  1422. y2 += ASCENT(font)+4;
  1423. pos += strlen(pos)+1;
  1424.     };
  1425.     free(dump);
  1426.         }
  1427.         if (active)
  1428.         {
  1429.             if (field->buflen > 0)
  1430.                 r = WIDTH(font, field->value, cursorpos);
  1431.             else
  1432.                 r = 0;
  1433.             XSetForeground(display, gc, strikeColor);
  1434.             XFillRectangle(display, win, gc, x1 + 3 + r, y2+2, 1, SPACING(Fonts[font]));
  1435.         }
  1436.         XSetForeground(display, gc, textColor);
  1437.         XSetClipRectangles(display, gc, 0, 0, &displayRect, 1, Unsorted);
  1438.     }
  1439. }
  1440. #endif