home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c070 / 4.ddi / TOOLS.4 / TCTSRC1.EXE / EDBASE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-31  |  13.7 KB  |  447 lines

  1. /**
  2. *
  3. * Name        EDBASE -- Edit and return a user response.
  4. *
  5. * Synopsis    error = edbase(pdata, pinitstr, pretstr, target_size,
  6. *                   pfield_control, pfinal_key, return_info,
  7. *                   set_cursor, write_rect);
  8. *
  9. *        ED_ACTION error         The returned status code.
  10. *        void *pdata            Pointer to data which will
  11. *                        be passed to return_info,
  12. *                        set_cursor, and write_rect.
  13. *        const char *pinitstr        The initial value of the
  14. *                        buffer.
  15. *        char *pretstr            The returned user response.
  16. *        int target_size         The maximum size of the
  17. *                        buffer, including the
  18. *                        trailing '\0'.
  19. *        const ED_CONTROL        Field display and editing
  20. *            *pfield_control        control structure.
  21. *        KEY_SEQUENCE *pfinal_key    Pointer to final keystroke
  22. *                        entered by user.
  23. *        PED_RET_FUNC return_info    Pointer to function which
  24. *                        will return cursor info.
  25. *        PED_SET_FUNC set_cursor     Pointer to function which
  26. *                        will set cursor state.
  27. *        PED_WRITE_FUNC write_rect   Pointer to function which
  28. *                        will write a rectangle of
  29. *                        screen data.
  30. *
  31. * Description    EDBASE provides a flexible method for gathering
  32. *        information from a screen field and returning the data
  33. *        in a formatted text string.
  34. *
  35. *        The field_control parameter is used to control where the
  36. *        field is placed on the screen, how long the diplayed
  37. *        buffer is, cursor size and general editing control.
  38. *
  39. *        The text contained in pinitstr (if any) is used as an
  40. *        initial value for the field, which the user will be
  41. *        allowed to edit.  The length of the text, including
  42. *        the trailing '\0', is not allowed to grow longer than
  43. *        target_size characters.
  44. *
  45. *        EDBASE is responsible for positioning the cursor,
  46. *        displaying the buffer, and formatting the buffer when it
  47. *        is finally transmitted.
  48. *
  49. *        Since EDBASE accepts pointers to functions which will
  50. *        perform all physical screen I/O for it, it is intended
  51. *        to be called via the macros EDFIELD and WNFIELD.
  52. *        The EDFIELD macro provides pointers to functions which
  53. *        perform their I/O on the screen itself, whereas WNFIELD
  54. *        provides functions which perform their I/O on a window.
  55. *
  56. * Returns    error        EDFIELD returns:
  57. *        ED_NO_ERROR   - Data successfully returned.
  58. *        ED_ILL_DIM    - Field dimensions are illegal.
  59. *        ED_NO_MEMORY  - No memory for temporary storage.
  60. *        ED_USER_ABORT - Editing aborted by user, no data
  61. *                returned.
  62. *                WNFIELD returns:
  63. *        WN_NO_ERROR   - Data successfully returned.
  64. *        WN_ILL_DIM    - Field dimensions are illegal.
  65. *        WN_NO_MEMORY  - No memory for temporary storage.
  66. *        WN_BAD_WIN    - *pdata points to a bad window structure.
  67. *        WN_ILL_VALUE  - Cursor dimensions are illegal.
  68. *        ED_USER_ABORT - Editing aborted by user, no data
  69. *                returned.
  70. *        b_wnerr     Unchanged if no error, otherwise
  71. *                same value as error.
  72. *
  73. *
  74. * Version    6.00 (C)Copyright Blaise Computing Inc.  1989
  75. *
  76. **/
  77. #include <butil.h>
  78. #include <bedit.h>
  79. #include <bstrings.h>
  80. #include <bvideo.h>
  81. #include <bwindow.h>
  82. #include <conio.h>
  83. #include <string.h>
  84. #include <stdio.h>
  85.  
  86.  
  87. int edbase(pdata, pinitstr, pretstr, target_size, pfield_control,
  88.        pfinal_key, return_info, set_cursor, write_rect)
  89. void         *pdata;
  90. const char     *pinitstr;
  91. char         *pretstr;
  92. int          target_size;
  93. const ED_CONTROL *pfield_control;
  94. KEY_SEQUENCE     *pfinal_key;
  95. PED_RET_FUNC      return_info;
  96. PED_SET_FUNC      set_cursor;
  97. PED_WRITE_FUNC      write_rect;
  98. {
  99.     int        row, col;
  100.     ED_BUFFER       edit_buffer;
  101.     int        buffer_length;
  102.     int        field_width, field_height;
  103.     int        cur_edit_row, cur_edit_col;
  104.     int        fore_attr, back_attr;
  105.     CUR_TYPE       replace_curs, insert_curs;
  106.     KEY_SEQUENCE   found_keyseq;
  107.     ED_KEY       edit_key;
  108.     ED_KEY      *pedit_key;
  109.     char       fill_char;
  110.     ED_ACTION       edit_action;
  111.     unsigned char  beep_on, done;
  112.     int        final_action;
  113.     int        error_code;
  114.     char      *ptemp_buffer;
  115.     int        just_code;
  116.     CUR_INFO       info;
  117.     int        error;
  118.     char      *ptemp_string = NIL;
  119.     int        nul_index;
  120.  
  121.     field_height = pfield_control->dimensions.h;
  122.     field_width  = pfield_control->dimensions.w;
  123.  
  124.     error = return_info(pdata, &info, &(pfield_control->ul_corner),
  125.             field_height, field_width);
  126.     if (error)
  127.     return(error);
  128.  
  129.         /* Set the initial field coordinates.            */
  130.     row = pfield_control->ul_corner.row;
  131.     col = pfield_control->ul_corner.col;
  132.  
  133.         /* Default attributes are the existing attributes   */
  134.         /* if foreground and background are both zero.        */
  135.     if (pfield_control->attribute == 0)
  136.     {
  137.     fore_attr = -1;
  138.     back_attr = -1;
  139.     }
  140.     else
  141.     {
  142.     fore_attr = uthinyb(pfield_control->attribute);
  143.     back_attr = utlonyb(pfield_control->attribute);
  144.     }
  145.  
  146.     if ((pfield_control->replace_cursor.high == -1) &&
  147.     (pfield_control->replace_cursor.low  == -1))
  148.     {
  149.     replace_curs = info.size;
  150.     }
  151.     else
  152.     replace_curs = pfield_control->replace_cursor;
  153.  
  154.     if ((pfield_control->insert_cursor.high == -1) &&
  155.     (pfield_control->insert_cursor.low  == -1))
  156.     {
  157.     insert_curs = info.size;
  158.     }
  159.     else
  160.     insert_curs = pfield_control->insert_cursor;
  161.  
  162.         /* Now initialize the edit buffer, edit_buffer. The */
  163.         /* previous values are set to the same values as    */
  164.         /* the current values.    The buffers are set to the  */
  165.         /* initial string, and length is the length of the  */
  166.         /* edit field.                        */
  167.     buffer_length = field_width * field_height;
  168.  
  169.     edit_buffer.pbuffer = malloc(buffer_length);
  170.     if (edit_buffer.pbuffer == NIL)
  171.     return(ED_NO_MEMORY);
  172.  
  173.     memset(edit_buffer.pbuffer, ' ', buffer_length);
  174.     edit_buffer.pbuffer[buffer_length - 1] = '\0';
  175.  
  176.     utuplim(buffer_length, target_size - 1);
  177.  
  178.         /* Set the edit buffer control flags so that        */
  179.         /* EDBUFFER will know what to do.            */
  180.     edit_buffer.control_flags = pfield_control->control_flags &
  181.                 (ED_INSERT_MODE | ED_WORD_WRAP);
  182.  
  183.     edit_buffer.buffer_size = buffer_length;
  184.     edit_buffer.cursor_pos  = 0;
  185.     edit_buffer.attribute   = utnybbyt(back_attr, fore_attr);
  186.     edit_buffer.dimensions  = pfield_control->dimensions;
  187.  
  188.     if (pinitstr != NIL)
  189.     {
  190.         /* If word wrap is specified, remove all leading    */
  191.         /* blanks from the buffer.                */
  192.     if ((pfield_control->control_flags & ED_WORD_WRAP) &&
  193.         isspace(pinitstr[0]))
  194.     {
  195.         ptemp_string = malloc(strlen(pinitstr));
  196.         if (ptemp_string == NIL)
  197.         {
  198.         free(edit_buffer.pbuffer);
  199.         return(ED_NO_MEMORY);
  200.         }
  201.         strcpy(ptemp_string, pinitstr);
  202.         stpcvt(ptemp_string, RLWHITE);
  203.         pinitstr = ptemp_string;
  204.     }
  205.  
  206.     if (strlen(pinitstr) <= buffer_length)
  207.         edit_buffer.data_end = strlen(pinitstr);
  208.     else
  209.         edit_buffer.data_end = buffer_length;
  210.     memmove(edit_buffer.pbuffer, pinitstr, edit_buffer.data_end);
  211.     }
  212.     else
  213.     edit_buffer.data_end = 0;
  214.  
  215.         /* Begin by applying word wrapping to the buffer,   */
  216.         /* if requested.                    */
  217.     if (pfield_control->control_flags & ED_WORD_WRAP)
  218.     {
  219.     edreduce(&edit_buffer);
  220.     edwrap(&edit_buffer);
  221.     }
  222.  
  223.         /* The main loop of EDBASE displays the current     */
  224.         /* buffer, and positions the cursor to the        */
  225.         /* appropriate position on the screen.    The current */
  226.         /* edit mode determines the size of the cursor. The */
  227.         /* function KBPOLL returns the keystroke by polling */
  228.         /* the keyboard.  The address of the key control    */
  229.         /* function is passed to KBPOLL, and the address of */
  230.         /* the edit buffer is passed as the function data.  */
  231.         /* The application key control function can        */
  232.         /* therefore inspect and alter the edit buffer if   */
  233.         /* it wishes.                        */
  234.  
  235.     beep_on = 0;
  236.     done    = 0;
  237.  
  238.     do
  239.     {
  240.     cur_edit_row = edit_buffer.cursor_pos / field_width;
  241.     cur_edit_col = edit_buffer.cursor_pos -
  242.                (field_width * cur_edit_row);
  243.  
  244.         /* Set the size & position of the cursor.        */
  245.     if (edit_buffer.control_flags & ED_INSERT_MODE)
  246.         error = set_cursor(pdata, 0, &insert_curs,
  247.                    row + cur_edit_row, col + cur_edit_col);
  248.     else
  249.         error = set_cursor(pdata, 0, &replace_curs,
  250.                    row + cur_edit_row, col + cur_edit_col);
  251.     if (error)
  252.     {
  253.         free(edit_buffer.pbuffer);
  254.         if (ptemp_string != NIL)
  255.         free(ptemp_string);
  256.         return(error);
  257.     }
  258.  
  259.         /* Display the data contained in the buffer.        */
  260.     write_rect(pdata, row, col,
  261.            row + field_height - 1,
  262.            col + field_width - 1,
  263.            edit_buffer.pbuffer, fore_attr,
  264.            back_attr, CHARS_ONLY);
  265.  
  266.         /* Now return the next keystroke.  If it is not a   */
  267.         /* recognized edit key (that is, it does not appear */
  268.         /* in the edit key list), the action code taken is  */
  269.         /* ED_ASCII (display as standard character), if the */
  270.         /* character code is nonzero. All other keys are    */
  271.         /* ignored (ED_NULL).                    */
  272.  
  273.     while (!kbpoll(pfield_control->control_function, &edit_buffer,
  274.                &found_keyseq, KB_REMOVE_KEY))
  275.         ;
  276.  
  277.     pedit_key = edretkey(&found_keyseq);
  278.  
  279.     if (pedit_key == NIL)
  280.     {
  281.         edit_action = (found_keyseq.character_code ? ED_ASCII
  282.                                : ED_NULL);
  283.         edit_key.key_sequence = found_keyseq;
  284.         edit_key.edit_actions.num_actions = 1;
  285.         edit_key.edit_actions.pactions = &edit_action;
  286.         pedit_key = &edit_key;
  287.     }
  288.  
  289.     final_action = edbuffer(&edit_buffer, pedit_key);
  290.  
  291.         /* If at the end of the buffer, check to see if     */
  292.         /* transmission should occur (ED_AUTOSKIP) or if    */
  293.         /* the system speaker should sound (ED_BEEP_END).   */
  294.     if (edit_buffer.cursor_pos == (buffer_length - 1))
  295.     {
  296.         if ((pfield_control->control_flags & ED_BEEP_END) != 0)
  297.         beep_on = 1;
  298.         if ((pfield_control->control_flags & ED_AUTOSKIP) != 0)
  299.         {
  300.         done      = 1;
  301.         error_code = ED_NO_ERROR;
  302.         }
  303.     }
  304.  
  305.     if (beep_on)
  306.     {
  307.         beep_on = 0;
  308.         scttywrt('\a', 0);
  309.     }
  310.  
  311.     switch (final_action)
  312.     {
  313.     case ED_ABORT:
  314.         done       = 1;
  315.         error_code = ED_USER_ABORT;
  316.         memset(edit_buffer.pbuffer, ' ', buffer_length);
  317.         edit_buffer.data_end = strlen(pinitstr);
  318.         utuplim(edit_buffer.data_end, buffer_length);
  319.         memmove(edit_buffer.pbuffer, pinitstr,
  320.             edit_buffer.data_end);
  321.         break;
  322.  
  323.     case ED_ATTR:
  324.         if (edit_buffer.attribute == 0)
  325.         {
  326.         fore_attr = -1;
  327.         back_attr = -1;
  328.         }
  329.         else
  330.         {
  331.         fore_attr = uthinyb(edit_buffer.attribute);
  332.         back_attr = utlonyb(edit_buffer.attribute);
  333.         }
  334.         break;
  335.  
  336.     case ED_UNDO:
  337.         memset(edit_buffer.pbuffer, ' ', buffer_length);
  338.         edit_buffer.cursor_pos = 0;
  339.         edit_buffer.data_end = strlen(pinitstr);
  340.         utuplim(edit_buffer.data_end, buffer_length - 1);
  341.         memmove(edit_buffer.pbuffer, pinitstr,
  342.             edit_buffer.data_end);
  343.         edit_buffer.attribute     = utnybbyt(back_attr, fore_attr);
  344.         edit_buffer.control_flags = pfield_control->control_flags &
  345.                     (ED_INSERT_MODE | ED_WORD_WRAP);
  346.         break;
  347.  
  348.     case ED_TRANSMIT:
  349.         done       = 1;
  350.         error_code = ED_NO_ERROR;
  351.         break;
  352.     }
  353.     }
  354.     while (!done);
  355.  
  356.     if (pfield_control->control_flags & ED_WORD_WRAP)
  357.     edreduce(&edit_buffer);
  358.  
  359.     if (pfinal_key != NIL)
  360.     *pfinal_key = found_keyseq;
  361.  
  362.     utuplim(edit_buffer.data_end, target_size - 1);
  363.     edit_buffer.pbuffer[edit_buffer.data_end] = '\0';
  364.  
  365.         /* Alter the buffer based on the control_flags        */
  366.         /* member of the pfield_control structure.  The low */
  367.         /* order byte is the conversion code to pass to     */
  368.         /* stpcvt().  The low order nybble of the high        */
  369.         /* order byte determines justification and fill     */
  370.         /* character.  Note that if justification is        */
  371.         /* specified, blank fill is the default.  Moreover, */
  372.         /* left justification takes precendence over right  */
  373.         /* justification.
  374.  
  375.     if (error_code == ED_NO_ERROR)    /* Only alter the buffer if */
  376.     {                    /* normal transmission.     */
  377.  
  378.     stpcvt(edit_buffer.pbuffer,
  379.            pfield_control->control_flags & 0xff);
  380.  
  381.         /* Now justify the string if requested.  Right        */
  382.         /* justification takes place within the entire edit */
  383.         /* buffer field, but left justification just within */
  384.         /* the string length.                    */
  385.     if ((pfield_control->control_flags &
  386.         (ED_LEFTJUST | ED_RIGHTJUST | ED_CENTERJUST)) != 0)
  387.     {
  388.         if ((pfield_control->control_flags & ED_ZERO_FILL) != 0)
  389.           fill_char = '0';
  390.         else
  391.           fill_char = ' ';
  392.  
  393.         if ((pfield_control->control_flags & ED_LEFTJUST) != 0)
  394.         just_code = -1;
  395.         else
  396.         if ((pfield_control->control_flags & ED_RIGHTJUST) != 0)
  397.             just_code = 1;
  398.         else
  399.             just_code = 0;
  400.  
  401.         ptemp_buffer = malloc(buffer_length + 1);
  402.         if (ptemp_buffer == NIL)
  403.         {
  404.         /* Error allocating temporary storage.            */
  405.         free(edit_buffer.pbuffer);
  406.         if (ptemp_string != NIL)
  407.             free(ptemp_string);
  408.         return(ED_NO_MEMORY);
  409.         }
  410.         stpjust(ptemp_buffer, edit_buffer.pbuffer, fill_char,
  411.             buffer_length, just_code);
  412.         memmove(edit_buffer.pbuffer, ptemp_buffer, buffer_length + 1);
  413.         free(ptemp_buffer);
  414.     }
  415.  
  416.     }
  417.         /* Now display any changes that were made to the    */
  418.         /* buffer.                        */
  419.     nul_index = strlen(edit_buffer.pbuffer);
  420.     memset(edit_buffer.pbuffer + nul_index, ' ',
  421.        buffer_length - nul_index);
  422.     write_rect(pdata, row, col,
  423.            row + field_height - 1,
  424.            col + field_width - 1,
  425.            edit_buffer.pbuffer, fore_attr,
  426.            back_attr, CHARS_ONLY);
  427.     edit_buffer.pbuffer[nul_index] = '\0';
  428.  
  429.         /* Restore the original state of the cursor.        */
  430.     error = set_cursor(pdata, info.off, &info.size,
  431.                info.row, info.col);
  432.     if (error)
  433.     {
  434.     free(edit_buffer.pbuffer);
  435.     if (ptemp_string != NIL)
  436.         free(ptemp_string);
  437.     return(error);
  438.     }
  439.  
  440.     strcpy(pretstr, edit_buffer.pbuffer);
  441.     free(edit_buffer.pbuffer);
  442.     if (ptemp_string != NIL)
  443.     free(ptemp_string);
  444.  
  445.     return(error_code);
  446. }
  447.