home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 09 / brief / binedit.cb < prev    next >
Text File  |  1991-06-03  |  46KB  |  1,467 lines

  1.  
  2. /*
  3. **    This set of macros and the accompanying executable were written by:
  4. **    Jim Rodriguez and Tim Hanna for editing hex and unix files.
  5. **    See the binread.me file for loading instructions and macro descriptions.
  6. **    
  7. **    If you do not want hex support for binary files, comment out the #define HEX
  8. **    If you do not want unix file support, comment out the #define UNIX
  9. **    If you do not want either, delete this file.
  10. **    Revision history:
  11. **     4/17/91 fixed bug in positioning after hex/ascii editing.
  12. **             added key assignment for alt-g to go to hex offset
  13. **             converted if to while when entering ascii/hex characters
  14. **             fixed a bug with keyboard manipulation
  15. **    
  16. **     4/18/91 added ability to change position when clicking mouse in ascii window
  17. **             fixed a bug in the mouse handling for set_win event with multiple windows
  18. */
  19. // $lgb$
  20. // April 19 91 1.0 binedit.cb JMR 
  21. // April 19 91 1.1 binedit.cb JMR 
  22. // April 19 91 1.2 binedit.cb JMR 
  23. // April 19 91 1.3 binedit.cb JMR 
  24. // April 19 91 1.4 binedit.cb JMR optimized movement macros into one function
  25. // April 19 91 1.5 binedit.cb JMR repositioned mouse action macro to correspond with ifdef
  26. // April 19 91 1.6 binedit.cb JMR 
  27. // April 19 91 1.7 binedit.cb JMR modified ascii search  prompt
  28. // April 25 91 1.8 binedit.cb JMR modified for 3.0 compatability
  29. // April 25 91 1.9 binedit.cb JMR added alt-d for delete line
  30. // April 25 91 1.10 binedit.cb JMR 
  31. // May 6 91 1.11 binedit.cb JMR modified search prompt
  32. // May 7 91 1.12 binedit.cb JMR modified bin_search bug fixed bug in bin_on for non-controlled buffers
  33. // May 7 91 1.13 binedit.cb JMR fixed bug in bin_on not setting buffer and fixed bin_search
  34. // May 7 91 1.14 binedit.cb JMR fixed bugs
  35. // May 10 91 1.15 binedit.cb JMR changed _on to a replacement macro
  36. // May 10 91 1.16 binedit.cb JMR modified _on to use the default _on macro and then superclass it
  37. // May 10 91 1.17 binedit.cb JMR Removed _on macro
  38. // May 15 91 1.18 binedit.cb JMR 
  39. // May 20 91 1.19 binedit.cb JMR added add_hex_keys modified write_buffer to use delete_curr_buffer
  40. // May 31 91 1.20 binedit.cb JMR modified _bin_atoh by removing the switch
  41. // May 31 91 1.21 binedit.cb JMR 
  42. // June 3 91 1.22 binedit.cb JMR cleaned up
  43. // June 3 91 1.23 binedit.cb JMR 
  44. // $lge$
  45. #define HEX
  46. #define UNIX
  47.  
  48. // This defines the number of iterations of the for loop for highlighting
  49.  
  50. // The current character in the ascii window.
  51. #define SHOW_DELAY 50
  52.  
  53. // These are for positioning in the buffer.
  54. #define UP      -10
  55. #define DOWN     10
  56. #define LEFT     -1
  57. #define RIGHT     1
  58. #define PGUP    -21
  59. #define PGDN     21
  60. #define TOP      30
  61. #define BOTTOM  -31
  62. #define HOME    -40
  63. #define END     -41
  64.  
  65. // Declare the _package_buf extern to access the package information and
  66. // the macros for calling template keyboards as well as the global strings
  67. // used for file extension specific next_word etc.
  68.  
  69. extern   _package_buf,
  70.          delete_curr_buffer,
  71.          .c_template_first,
  72.          .for_template_first,
  73.          .ada_template_first,
  74.          .mod_template_first,
  75.          .prg_smart_first,
  76.          _regular_first,
  77.          .pas_template_first,
  78.          .bas_template_first,
  79.          .cob_template_first;
  80.  
  81. int   __unix_files, __hex_files;
  82.  
  83. #ifdef HEX
  84.    int   __bin_keyboard, __hex_window, __asc_window;
  85. #endif
  86.  Create system buffers for holding filenames.
  87. _init ()
  88. {
  89.  
  90.     system buffer for holding UNIX files
  91.    __unix_files = create_buffer ("UNIXFILE", NULL, 1);
  92.     system buffer for holding HEX files
  93.    __hex_files = create_buffer ("HEXFILES", NULL, 1);
  94.  
  95. #ifdef UNIX
  96.    // Register a macro for trapping files with no CR/LF.
  97.    register_macro (6, "_unix_edit");
  98. #endif
  99.  
  100. #ifdef HEX
  101.  
  102.    // Register a macro for trapping Null chars message.
  103.    register_macro (6, "_bin_edit");
  104.  
  105.    // Create the editing keyboard
  106.    keyboard_push ();
  107.    set_mouse_action("_bin_mouse");
  108.    add_hex_keys();
  109.    __bin_keyboard = inq_keyboard ();
  110.    keyboard_pop (1);
  111. #endif
  112. }
  113. #ifdef HEX
  114. // This macro adds the hex editing keys 0-F and function keys hex buffer
  115. add_hex_keys()
  116. {
  117.    string macro_name, key_name;
  118.    int loop;
  119.    for (loop=48;loop<58;loop++)  // Use ascii codes for 0-9
  120.    {
  121.       sprintf (key_name, "<%c>",loop);
  122.       sprintf (macro_name, "_bin_add \"%c\"",loop);
  123.       assign_to_key (key_name, macro_name);
  124.    }
  125.    for (loop=65;loop<71;loop++)  // Use ascii codes for a-f A-F
  126.    {
  127.       sprintf (key_name, "<%c>",loop);
  128.       sprintf (macro_name, "_bin_add \"%c\"",loop);
  129.       assign_to_key (key_name, macro_name);
  130.       assign_to_key (lower(key_name), macro_name);
  131.    }
  132.    assign_to_key ("<Enter>", "_bin_ascii");      // Type ascii character
  133.    assign_to_key ("<Ctrl-Enter>", "_bin_open");  // Add a new line
  134.    assign_to_key ("<F10>", "execute_macro");     // Just in case
  135.    assign_to_key ("<Alt-n>", "edit_next_buffer");// Next buffer
  136.    assign_to_key ("<Alt-d>", "_bin_delete 1");   // Delete a line
  137.    assign_to_key ("<Alt-e>", "edit_file");       // Edit file
  138.    assign_to_key ("<Alt-g>", "_bin_offset");     // Goto offset
  139.    assign_to_key ("<Alt-u>", "undo 1");          // Undo
  140.    assign_to_key ("<Ctrl-u>", "redo");           // Redo
  141.    assign_to_key ("<Alt-w>", "write_buffer");    // Write buffer and reconvert
  142.    assign_to_key ("<Del>", "_bin_delete");       // Delete byte
  143.    assign_to_key ("<F5>", "_bin_search");        // Search for bytes
  144.    assign_to_key ("<Alt-F5>", "_bin_ascii_search"); // Search the ascii buffer
  145.    assign_to_key ("<Alt-x>", "exit");            // Exit Brief
  146.    assign_to_key ("<Esc>", "_bin_show_match");   // Show corresponding position
  147.  
  148.    // Sprintf used with #defines for movement keys
  149.    sprintf (macro_name, "_bin_move %d", UP);
  150.    assign_to_key ("<Up>", macro_name);
  151.    sprintf (macro_name, "_bin_move %d", DOWN);
  152.    assign_to_key ("<Keypad-Enter>", macro_name);
  153.    assign_to_key ("<Down>", macro_name);
  154.    sprintf (macro_name, "_bin_move %d", LEFT);
  155.    assign_to_key ("<Left>", macro_name);
  156.    sprintf (macro_name, "_bin_move %d", RIGHT);
  157.    assign_to_key ("<Right>", macro_name);
  158.    sprintf (macro_name, "_bin_move %d", PGUP);
  159.    assign_to_key ("<PgUp>", macro_name);
  160.    sprintf (macro_name, "_bin_move %d", PGDN);
  161.    assign_to_key ("<PgDn>", macro_name);
  162.    sprintf (macro_name, "_bin_move %d", TOP);
  163.    assign_to_key ("<Ctrl-Pgup>", macro_name);
  164.    sprintf (macro_name, "_bin_move %d", BOTTOM);
  165.    assign_to_key ("<Ctrl-PgDn>", macro_name);
  166.    sprintf (macro_name, "_bin_move %d", HOME);
  167.    assign_to_key ("<Home>", macro_name);
  168.    sprintf (macro_name, "_bin_move %d", END);
  169.    assign_to_key ("<End>", macro_name);
  170. }
  171. #endif
  172. /*
  173. **    A replacement for write_buffer to check file extension and clean up the
  174. **    system buffers.  Be aware that the conversion back to binary/UNIX will not
  175. **    occur if the buffer has not been modified.
  176. */
  177. replacement int write_buffer ()
  178. {
  179.    int   buf_to_edit,
  180.          buf_to_delete,
  181.          file_is_controlled,
  182.          file_was_modified;
  183.  
  184.    string   file_name,
  185.             ext,
  186.             response,
  187.             response2,
  188.             old_buffer,
  189.             write_command;
  190.  
  191.    inq_names (file_name, ext);
  192.  
  193.    // If write_buffer was not called from the keyboard and the extension
  194.    // isn't .hex or .unx call write_buffer.  Otherwise, get some input and go to work.
  195.    if ("" == inq_called () && (ext == "hex" || ext == "unx"))
  196.       if (get_parm (0, response, "Convert file? ", 1, "Y"))
  197.          if (get_parm (1, response2, "Delete buffer? ", 1, "Y"))
  198.          {
  199.             int   file_is_hex,
  200.                   msg_lvl;
  201.  
  202.             file_is_hex = 0;
  203.             // Get the current buffer id to delete.
  204.             buf_to_edit = inq_buffer ();
  205.             raise_anchor ();
  206.  
  207.             // If the file is modified set a flag and write the buffer.
  208.             if (inq_modified ())
  209.             {
  210.                msg_lvl = inq_msg_level ();
  211.                set_msg_level (0);
  212.                returns write_buffer ();
  213.                set_msg_level (msg_lvl);
  214.                file_was_modified = 1;
  215.             }
  216.             // Otherwise, we don't need to do the conversion.
  217.             else
  218.                file_was_modified = 0;
  219.  
  220.             // Parse the file name to remove the extension.
  221.             if (index (file_name, "."))
  222.                file_name = substr (file_name, 1, rindex (file_name, ".") - 1);
  223.  
  224.             // Remove the line in the system buffer which controls the file.
  225.             if (ext == "hex")
  226.             {
  227.                set_buffer (__hex_files);
  228.                file_is_hex = 1;
  229.             }
  230.             else
  231.                set_buffer (__unix_files);
  232.             top_of_buffer ();
  233.  
  234.             // Be aware that regular expressions CANNOT be used in the
  235.             // search.
  236.             if (search_fwd (file_name + ",ext=", 0, 0))
  237.                // Parse the line to get the original extension and locate
  238.                // the associated system buffer.
  239.             {
  240.                beginning_of_line ();
  241.                ext = trim (read ());
  242.                file_is_controlled=1;
  243.  
  244.                // Find the system buffer.
  245.                if (file_is_hex)
  246.                {
  247.                   int temp_buffer=inq_buffer();
  248.                   ext = ltrim (substr (ext, index (ext, "newb=") + 5));
  249.                   old_buffer = substr (ext, 1, 10);
  250.  
  251.                   // Convert to a valid buffer id.
  252.                   buf_to_delete = atoi (old_buffer, 1);
  253.  
  254.                   set_buffer(buf_to_delete);
  255.                   raise_anchor();
  256.                   write_buffer();
  257.                   drop_anchor(2);
  258.                   set_buffer(temp_buffer);
  259.                   if (upper (response2) == "Y")
  260.                      delete_buffer (buf_to_delete);
  261.                }
  262.                // Find the original extension
  263.                ext = trim (substr (ext, rindex (ext, "=") + 1));
  264.  
  265.                beginning_of_line ();
  266.                if (upper (response2) == "Y")
  267.                   // Delete the reference to the file.
  268.                   delete_line ();
  269.             }
  270.             // Reset the buffer to the original buffer.
  271.             set_buffer (buf_to_edit);
  272.  
  273.             // Create the dos line.
  274.             if (file_is_hex)
  275.                sprintf (write_command, "bbe HB %s.hex %s.%s>&nul", file_name, file_name, ext);
  276.             else
  277.                sprintf (write_command, "bbe DU %s.unx %s.%s>&nul", file_name, file_name, ext);
  278.             if (file_was_modified && upper (response) == "Y" && file_is_controlled)
  279.             // If the modified flag is not set we won't bother doing the
  280.             // conversion.
  281.             {
  282.                message ("%s", write_command);
  283.                dos (write_command);
  284.                message ("Conversion complete");
  285.             }
  286.  
  287.             // Now, delete the current buffer and the converted file.
  288.             if (upper (response2) == "Y")
  289.             {
  290.                if (1 != delete_curr_buffer())
  291.                {
  292.                   file_is_controlled=-1;
  293.                   delete_buffer(buf_to_edit);
  294.                }
  295.                if (file_is_hex)
  296.                {
  297.                   sprintf (response, "%s.hex", file_name);
  298.                   del (response);
  299.                   sprintf (response, "%s.asc", file_name);
  300.                }
  301.                else
  302.                   sprintf (response, "%s.unx", file_name);
  303.                del (response);
  304.                if (file_is_controlled == -1)
  305.                   exit("y");
  306.             }
  307.             else
  308.                if (file_is_hex && file_is_controlled)
  309.                {
  310.                   move_rel (0, -1);
  311.                   drop_anchor ();
  312.                   move_rel (0, 1);
  313.                }
  314.             }
  315.          else ;
  316.       else ;
  317.    else
  318.       return write_buffer ();
  319. }
  320.  
  321. #ifdef HEX
  322. // This function accepts a "hex" string and returns an integer.
  323. int _bin_atoh (string to_convert)
  324. {
  325.    string   str_rev;
  326.  
  327.    int   converted,
  328.          loop_count,
  329.          t_int;
  330.  
  331.    get_parm (0, to_convert);
  332.  
  333.    // Method is to read a character from the end of the string and multiply
  334.    // it by the loop count which is multiplied by 16 on each iteration.
  335.    while (strlen (trim (to_convert)))
  336.       // Start from the end of the string.
  337.       {
  338.       str_rev = substr (to_convert, strlen (to_convert), 1);
  339.  
  340.       // Convert to an integer and store in a temporary variable.
  341.       t_int = index("123456789ABCDEF",upper(str_rev));
  342.  
  343.       // Multiply the loop counter by 16 for the base conversion.
  344.       loop_count *= 16;
  345.  
  346.       // If the first time through, start the counter.
  347.       if (0 == loop_count)
  348.          loop_count = 1;
  349.  
  350.       // Add the temp variable to the sum.
  351.       converted += t_int * loop_count;
  352.  
  353.       // Remove the last character from the string.
  354.       to_convert = substr (to_convert, 1, strlen (to_convert) - 1);
  355.       }
  356.    // Return the integer.
  357.    return converted;
  358. }
  359. // This macro displays the current file offset in decimal and hex.
  360. void _bin_disp_offset ()
  361. {
  362.    int   hl,
  363.          hc,
  364.          offset;
  365.  
  366.    string   char;
  367.  
  368.    inq_position (hl, hc);
  369.    offset = (hl - 1) * 25;
  370.    offset += hc / 2;
  371.    move_rel (0, -1);
  372.    char = read (2);
  373.    move_rel (0, 1);
  374.    hl = _bin_atoh (char);
  375.    switch (hl)
  376.       {
  377.       case 0:
  378.          {
  379.          char = "<NULL>";
  380.          message ("Offset: %u decimal, %08x hex, %s ascii", offset, offset, char);
  381.          }
  382.       case 255:
  383.       case 20:
  384.          {
  385.          char = "<SPACE>";
  386.          message ("Offset: %u decimal, %08x hex, %s ascii", offset, offset, char);
  387.          }
  388.       default:
  389.          message ("Offset: %u decimal, %08x hex, %c ascii", offset, offset, hl);
  390.       }
  391. }
  392. // This macro associates a system buffer with a hex buffer and modifies the
  393. // package information for .hex files
  394. void _hex_edit (string file_name, int in_memory)
  395. {
  396.    int   __hex_buffer,
  397.          __asc_buffer,
  398.          tmp_buf,
  399.          current_buffer;
  400.  
  401.    string   buffer_name,
  402.             file_ext,
  403.             buffer_id,
  404.             file_path;
  405.  
  406.    global   __hex_buffer,
  407.             __asc_buffer;
  408.  
  409.    // get the file name
  410.    if (get_parm (0, file_name))
  411.       {
  412.       get_parm (1, in_memory);
  413.       // parse the file name into path and extension
  414.       if (index (file_name, "."))
  415.          {
  416.          file_ext = substr (file_name, 1 + rindex (file_name, "."));
  417.          file_name = substr (file_name, 1, rindex (file_name, ".") - 1);
  418.          }
  419.       else
  420.          file_ext = "";
  421.       // parse off the path for the buffer name
  422.       buffer_name = substr (file_name, rindex (file_name, "\\") + 1);
  423.  
  424.       // store the current id to possible deletion
  425.       current_buffer = inq_buffer ();
  426.  
  427.       // If the macro was called from the registed macro delete the current
  428.       // buffer
  429.       if (inq_called () == "_bin_edit")
  430.          delete_buffer (current_buffer);
  431.  
  432.       // Try to create the buffer to check for existing buffer id
  433.       tmp_buf = create_buffer (buffer_name + ".hex", file_name + ".hex", 0);
  434.  
  435.       // If a valid buffer exists, continue
  436.       if (tmp_buf)
  437.          // See if the hex file is already being edited
  438.          {
  439.          set_buffer (__hex_files);
  440.          top_of_buffer ();
  441.          if (search_fwd (file_name + ",", 0, 0))
  442.  
  443.             // The hex file is being edited called edit_file and return
  444.             edit_file (file_name + ".hex");
  445.          else
  446.             // It's a new conversion delete the validity check buffer
  447.             {
  448.             delete_buffer (tmp_buf);
  449.  
  450.             // Create the dos string from the file name
  451.             sprintf (file_path, "bbe BH %s.%s %s.hex %s.asc>&nul", file_name, file_ext, file_name, file_name);
  452.  
  453.             // Do the hex files already exist?
  454.             if (!exist (file_name + ".hex") && !exist (file_name + ".asc"))
  455.                // Call dos for the conversion
  456.                {
  457.                message ("Generating hex file");
  458.                dos (file_path);
  459.                }
  460.             else
  461.                message ("Editing existing files.");
  462.             // Edit the hex and ascii representation of the file
  463.             __hex_buffer = create_buffer (buffer_name + ".hex", file_name + ".hex", 0);
  464.             __asc_buffer = create_buffer (buffer_name + ("." + file_ext), file_name + ".asc", 1);
  465.  
  466.             // We now have the buffer ids for both files as well as the filename and
  467.             // extension.  Save them in the hex_files system buffer for later.
  468.             sprintf (buffer_id, "oldb=%10d,newb=%10d,file=%s,ext=%s", __hex_buffer, __asc_buffer, file_name, file_ext);
  469.             set_buffer (__hex_files);
  470.             beginning_of_line ();
  471.             insert (buffer_id + "\n");
  472.  
  473.             // Make the hex file current and highlight the
  474.             // first byte.
  475.             set_buffer (__hex_buffer);
  476.             top_of_buffer ();
  477.             drop_anchor ();
  478.             move_rel (0, 1);
  479.  
  480.             // Access the package buffer and configure for the hex extension
  481.             if (first_time ())
  482.                // Make sure the user has the language macro loaded.
  483.                {
  484.                if (!_package_buf)
  485.                   load_macro ("language");
  486.  
  487.                // Edit the package buffer
  488.                set_buffer (_package_buf);
  489.                top_of_buffer ();
  490.  
  491.                // Delete any dribble which may have been erroneously set.
  492.                while (search_fwd ("<.hex", 1, 0))
  493.                   delete_line ();
  494.  
  495.                // Add the correct lines in packages to make this work.
  496.                insert (".hex_equivalents\n");
  497.                insert (".hex_existing;\n");
  498.                insert (".hex_first;.hex_template_first\n");
  499.                insert (".hex_on;_on,_bin_on\n");
  500.                insert (".hex;=hex,,=hex,,t\n");
  501.                top_of_buffer ();
  502.                }
  503.  
  504.             // Prepare to edit the hex buffer.
  505.             set_buffer (__hex_buffer);
  506.  
  507.             // The registed macros may not have been called if
  508.             // called from the keyboard.
  509.             if (0 != in_memory)
  510.                call_registered_macro (1);
  511.             }
  512.          }
  513.       }
  514. }
  515. // Registered macro for trapping Null files message.
  516. void _bin_edit ()
  517. {
  518.    if (inq_message () == "Null characters in file fixed.")
  519.       {
  520.       string   okay;
  521.  
  522.       string   file;
  523.  
  524.       inq_names (file);
  525.  
  526.       // See if the conversion is requested.
  527.       if (get_parm (0, okay, "Okay to create HEX file to edit? ", 1, "Y"))
  528.          if (upper (okay) == "Y")
  529.  
  530.             // Call _hex_edit to do the dirty work.
  531.             _hex_edit (file, 0);
  532.  
  533.          // Otherwise, let the user frustrate themselves.
  534.          else
  535.             message ("You asked for it.");
  536.  
  537.       }
  538. }
  539. // This macro allows editing of a file as a hex file from the keyboard.
  540. void edit_hex_file ()
  541. {
  542.    string   file_name,
  543.             last_message;
  544.  
  545.    int   ret_val;
  546.  
  547.    // Get the file name to convert
  548.    if (get_parm (0, file_name, "File to convert: "))
  549.       {
  550.       int   msgl;
  551.  
  552.       msgl = inq_msg_level ();
  553.  
  554.       // Set the message level to display all messages
  555.       set_msg_level (0);
  556.  
  557.       // Call edit_file to do the filename validation.
  558.       ret_val = edit_file (file_name);
  559.       set_msg_level (msgl);
  560.       last_message = inq_message ();
  561.  
  562.       // Get the full path name and write the buffer before conversion
  563.       inq_names (file_name);
  564.       if (inq_modified () && 1 == ret_val)
  565.          write_buffer ();
  566.  
  567.       // If there were nulls in the file the registered macro should deal
  568.       // with it
  569.       if (ret_val > 0 && last_message != "Null characters in file fixed.")
  570.          // Call the _hex_edit macro with the valid name
  571.          {
  572.          if (exist (file_name))
  573.             _hex_edit (file_name, ret_val);
  574.          }
  575.       }
  576. }
  577.  
  578. // This macro gets called for all .hex files. It is required to disassociate
  579. // the local keyboard attached to the .hex buffer.
  580. string .hex_template_first ()
  581. {
  582.    use_local_keyboard (0);
  583.    returns "";
  584. }
  585.  
  586. /*
  587. **    This macro edits the hex and ascii files in side by side windows by
  588. **    creating and moving an edge.  It insures the correct local keyboard
  589. **    by setting it explicitly.  We look in the hex_files buffer for the filename
  590. **    and extract the buffer ids.  Associate the buffers with windows and return.
  591. */
  592. string _bin_on ()
  593. {
  594.    int   i;
  595.  
  596.    string   buf_to_find,
  597.             exten;
  598.  
  599.    // Get the filename and parse off the extension.
  600.    inq_names (buf_to_find, exten);
  601.    buf_to_find = substr (buf_to_find, 1, (rindex (buf_to_find, exten) - strlen (exten)) + 1);
  602.    i=inq_buffer();
  603.    // Edit the system buffer to find buffer id's.
  604.    set_buffer (__hex_files);
  605.    top_of_buffer ();
  606.    // Find the line with the filename.
  607.    if (search_fwd (buf_to_find + ",", 0, 0))
  608.       // Parse the line to retrieve the buffer id's.
  609.       {
  610.       keyboard_flush();
  611.       use_local_keyboard (0);
  612.       keyboard_push (__bin_keyboard);
  613.       set_mouse_action("_bin_mouse");
  614.  
  615.       beginning_of_line ();
  616.       buf_to_find = trim (read ());
  617.       buf_to_find = ltrim (substr (buf_to_find, index (buf_to_find, "oldb=") + 5, 10));
  618.       __hex_buffer = atoi (buf_to_find, 1);
  619.       beginning_of_line ();
  620.       buf_to_find = read ();
  621.       buf_to_find = ltrim (substr (buf_to_find, index (buf_to_find, "newb=") + 5, 10));
  622.       __asc_buffer = atoi (buf_to_find, 1);
  623.       set_buffer (__hex_buffer);
  624.  
  625.       // Unregister the registered macro so a recursive situation does not
  626.       // arise from the window manipulations.
  627.       unregister_macro (1, "_call_on_packages");
  628.       create_edge (3);
  629.       __hex_window = inq_window ();
  630.       move_edge (1, 12);
  631.       change_window (1);
  632.  
  633.       // Attach the associated ascii system buffer to the window.
  634.       __asc_window = inq_window ();
  635.       attach_buffer (__asc_buffer);
  636.  
  637.       // Highlight the character.
  638.       if (!inq_marked ())
  639.          drop_anchor (2);
  640.       else
  641.          refresh ();
  642.       refresh ();
  643.       change_window (3);
  644.  
  645.       // Reregister the language macro.
  646.       register_macro (1, "_call_on_packages");
  647.  
  648.       // Display the file offset.
  649.       _bin_disp_offset ();
  650.  
  651.       // Return the off event for the language package.
  652.       returns "_bin_off";
  653.       }
  654.    // Otherwise, something got screwed up return nothing so as not to
  655.    // propagate the error.
  656.    else
  657.    {
  658.       set_buffer(i);
  659.       returns "";
  660.    }
  661. }
  662.  
  663. // This macro deletes the edge created in the on event.  The keyboard is popped
  664. // and recreated.
  665. void _bin_off ()
  666. {
  667.    keyboard_flush();
  668.    keyboard_pop ();
  669.    keyboard_push ();
  670.    add_hex_keys();
  671.    __bin_keyboard = inq_keyboard ();
  672.    delete_edge (1);
  673.    keyboard_pop (1);
  674.    set_mouse_action("_mouse_action");
  675. }
  676. // This function emulates a goto_line macro using a byte offset.
  677. void _bin_offset()
  678. {
  679.    int line,
  680.       col,
  681.       col2,
  682.       line2;
  683.    string input;
  684.    if (get_parm (NULL, input, "Enter Hex offset: "))
  685.    {
  686.       line2 = _bin_atoh(input);
  687.       line = line2 / 25;
  688.       line++;
  689.       line2 = line2 % 25;
  690.       col = line2 * 2;
  691.       save_position();
  692.       raise_anchor ();
  693.       move_rel(0,-1);
  694.       unregister_macro (1, "_call_on_packages");
  695.       if (move_abs(line,col))
  696.       {
  697.          inq_position(line2,col2);
  698.          if (line2==line && col2 == col)
  699.          {
  700.             restore_position(0);
  701.             move_rel(0,-1);
  702.             set_window (__asc_window);
  703.             raise_anchor ();
  704.             move_abs(line,col / 2);
  705.             drop_anchor (2);
  706.             refresh ();
  707.             set_window (__hex_window);
  708.          }
  709.          else
  710.             restore_position();
  711.       }
  712.       else
  713.          restore_position();
  714.       drop_anchor ();
  715.       move_rel (0, 1);
  716.       register_macro (1, "_call_on_packages");
  717.       refresh ();
  718.       _bin_disp_offset ();
  719.    }
  720. }
  721. // This macro adds a line to the hex file for insertions.
  722. void _bin_open ()
  723. {
  724.    int   loop_count;
  725.  
  726.    raise_anchor ();
  727.    end_of_line ();
  728.    insert ("\n");
  729.    for (loop_count = 0; loop_count < 25; loop_count++)
  730.       insert ("XX");
  731.    beginning_of_line ();
  732.    unregister_macro (1, "_call_on_packages");
  733.    set_window (__asc_window);
  734.    end_of_line ();
  735.    raise_anchor ();
  736.    insert ("\n");
  737.    for (loop_count = 0; loop_count < 25; loop_count++)
  738.       insert (".");
  739.    beginning_of_line ();
  740.    drop_anchor (2);
  741.    refresh ();
  742.    set_window (__hex_window);
  743.    drop_anchor ();
  744.    move_rel (0, 1);
  745.    register_macro (1, "_call_on_packages");
  746.    refresh ();
  747.    _bin_disp_offset ();
  748. }
  749. // This macro handles simutaneous positioning
  750. void _bin_move (int direction)
  751. {
  752.    int   col,
  753.          line;
  754.  
  755.    get_parm(0,direction);
  756.    raise_anchor ();
  757.    unregister_macro (1, "_call_on_packages");
  758.    set_window (__asc_window);
  759.    raise_anchor ();
  760.    inq_position (line, col);
  761.    switch (direction)
  762.    {
  763.       case LEFT:
  764.       case RIGHT:
  765.       {
  766.          if ((col == 25 && direction == RIGHT)|| (col==1 && direction==LEFT))
  767.          {
  768.             move_rel (direction,0);
  769.             col = (direction == LEFT ? 25 : 1);
  770.             move_abs (0,col);
  771.          }
  772.          else
  773.             move_rel (0,direction);
  774.       }
  775.       case UP:
  776.       case DOWN:
  777.       {
  778.          move_rel (direction / 10,0);
  779.       }
  780.       case PGUP:
  781.       case PGDN:
  782.       {
  783.          inq_window_size(line);
  784.          move_rel ((direction % 20) * line,0);
  785.       }
  786.       case HOME:
  787.          move_abs(0,1);
  788.       case END:
  789.          move_abs(0,25);
  790.       case TOP:
  791.             move_abs(1,1);
  792.       case BOTTOM:
  793.       {
  794.  
  795.          end_of_buffer();
  796.          move_abs(0,25);
  797.       }
  798.    }
  799.    while (inq_position (line,col))
  800.       move_rel (-1, 0);
  801.    drop_anchor (2);
  802.    refresh ();
  803.    set_window (__hex_window);
  804.    move_abs(line,col * 2);
  805.    move_rel (0, -1);
  806.    drop_anchor ();
  807.    move_rel (0, 1);
  808.    refresh ();
  809.    register_macro (1, "_call_on_packages");
  810.    _bin_disp_offset ();
  811. }
  812. // This macro is assigned to the enter key to prompt for an ascii character to
  813. // insert rather than having to edit with hex values.
  814. void _bin_ascii ()
  815. {
  816.    string   ascii_edit,
  817.             ascii_tmp;
  818.  
  819.    int   hex_val,
  820.          hex_tmp;
  821.  
  822.    // Get the character to replace with.
  823.    while (get_parm (0, ascii_edit, "Enter ascii character: ", 1))
  824.       // Only replace with a valid character.
  825.       {
  826.       if (strlen (ascii_edit))
  827.          // Convert to HEX.
  828.          {
  829.          hex_val = atoi (ascii_edit, 0);
  830.  
  831.          // Insure the user didn't enter anything stupid.
  832.          switch (hex_val)
  833.             {
  834.             case 13:
  835.             case 9:
  836.                ascii_edit = ".";
  837.             }
  838.  
  839.          // Create a HEX string.
  840.          sprintf (ascii_tmp, "%02x", hex_val);
  841.  
  842.          // Reposition the cursor change windows and insert the
  843.          // correct characters in the corresponding buffers and
  844.          // rehighlight the current byte.
  845.          raise_anchor ();
  846.          move_rel (0, -1);
  847.  
  848.          // Unregister the language macro for the window manipulations.
  849.          unregister_macro (1, "_call_on_packages");
  850.          set_window (__asc_window);
  851.          insert ("%s", ascii_edit);
  852.          raise_anchor ();
  853.  
  854.          // Delete the old character.
  855.          delete_char ();
  856.          move_rel (0, -1);
  857.          drop_anchor (2);
  858.          refresh ();
  859.          set_window (__hex_window);
  860.          insert ("%s", upper (ascii_tmp));
  861.  
  862.          // Delete the old characters.
  863.          delete_char (2);
  864.          move_rel (0, -1);
  865.          move_rel (0, -1);
  866.          drop_anchor ();
  867.          move_rel (0, 1);
  868.          refresh ();
  869.          _bin_move(1);
  870.  
  871.          // Reregister the language macro.
  872.          register_macro (1, "_call_on_packages");
  873.          }
  874.       }
  875.    _bin_disp_offset ();
  876. }
  877. // This function highlights the current character in the ascii buffer.
  878. void _bin_show_match ()
  879. {
  880.    int   i;
  881.  
  882.    if (__asc_window != inq_window () && __asc_window)
  883.       {
  884.       unregister_macro (1, "_call_on_packages");
  885.       set_window (__asc_window);
  886.       for (i = 0; i < SHOW_DELAY; i++)
  887.          refresh ();
  888.       set_window (__hex_window);
  889.       register_macro (1, "_call_on_packages");
  890.       _bin_disp_offset ();
  891.       }
  892.    // Otherwise, the ascii window is current i.e. it was called by the mouse
  893.    else
  894.       for (i = 0; i < SHOW_DELAY; i++)
  895.          refresh ();
  896. }
  897.  
  898. // This macro overwrites the byte in the hex window.  It is assigned to all of
  899. // the valid hex editing keys and uses push_back to get the original key.
  900. void _bin_add (string key_read)
  901. {
  902.    string   character,
  903.             sread;
  904.  
  905.    int   hex_val,
  906.          temp_hex;
  907.  
  908.    // Get the parameter which is the key pressed and push it back so it
  909.    // displays in the prompt as if it were typed.
  910.    get_parm (0, key_read);
  911.    push_back (key_to_int (key_read));
  912.    raise_anchor ();
  913.  
  914.    // Read the text from the buffer to display the old value at the prompt.
  915.    move_rel (0, -1);
  916.    sread = "Enter new value for ";
  917.    if (read (1) != "\n")
  918.       sread += read (2);
  919.    sread += ": ";
  920.    if (get_parm (1, character, sread, 2))
  921.       // Convert the "hex" string to an integer.
  922.       {
  923.       hex_val = _bin_atoh (character);
  924.  
  925.       // Convert the integer to a hex value.
  926.       sprintf (character, "%02x", hex_val);
  927.  
  928.       unregister_macro (1, "_call_on_packages");
  929.       set_window (__asc_window);
  930.  
  931.       // Make sure the value is insertable.
  932.       switch (hex_val)
  933.          {
  934.          case 13:
  935.          case 9:
  936.          case 0:
  937.             sread = ".";
  938.          default:
  939.             sprintf (sread, "%c", hex_val);
  940.          }
  941.  
  942.       // Insert the value in the hex and ascii buffers rehighlight and
  943.       // return.
  944.       raise_anchor ();
  945.       delete_char ();
  946.       insert ("%s", sread);
  947.       move_rel(0,-1);
  948.       drop_anchor (2);
  949.       refresh ();
  950.       set_window (__hex_window);
  951.       delete_char (2);
  952.       insert ("%s", upper (character));
  953.       }
  954.    drop_anchor ();
  955.    move_rel (0, 1);
  956.    refresh ();
  957.    register_macro (1, "_call_on_packages");
  958.    refresh ();
  959.    execute_macro(inq_assignment("<Right>"));
  960.    _bin_disp_offset ();
  961. }
  962. // This macro converts the current byte to XX which will not be process when
  963. // converted.
  964. void _bin_delete (int line)
  965. {
  966.    get_parm(0,line);
  967.    unregister_macro (1, "_call_on_packages");
  968.    set_window (__asc_window);
  969.    raise_anchor ();
  970.    if (line)
  971.    {
  972.       save_position();
  973.       move_abs(0,1);
  974.       drop_anchor(3);
  975.       translate("?",".",1,1,1,1);
  976.       raise_anchor ();
  977.       restore_position();
  978.    }
  979.    else
  980.    {
  981.       delete_char ();
  982.       insert (".");
  983.       move_rel (0, -1);
  984.    }
  985.    drop_anchor (2);
  986.    refresh ();
  987.    set_window (__hex_window);
  988.    raise_anchor ();
  989.    if (line)
  990.    {
  991.       save_position();
  992.       move_abs(0,1);
  993.       drop_anchor(3);
  994.       translate("?","X",1,1,1,1);
  995.       raise_anchor ();
  996.       restore_position();
  997.       move_rel (0, -1);
  998.    }
  999.    else
  1000.    {
  1001.       move_rel (0, 1);
  1002.       insert ("XX");
  1003.       move_rel (0, -4);
  1004.       delete_char (2);
  1005.    }
  1006.    drop_anchor ();
  1007.    move_rel (0, 1);
  1008.    register_macro (1, "_call_on_packages");
  1009.    refresh ();
  1010.    _bin_disp_offset ();
  1011. }
  1012. // This macro does a search on the ascii file.
  1013. void _bin_ascii_search ()
  1014. {
  1015.    string   str1,
  1016.             str2;
  1017.  
  1018.    if (get_parm (0, str1, "Enter ascii search pattern: "))
  1019.       // Add the regular expression while parsing the string into characters.
  1020.       {
  1021.       while (strlen (str1))
  1022.          {
  1023.          str2 += substr (str1, 1, 1);
  1024.          str2 += "[\n]@";
  1025.          str1 = substr (str1, 2);
  1026.          }
  1027.       // If a string exist, search.
  1028.       if (strlen (str2))
  1029.          {
  1030.          int   mark_length;
  1031.  
  1032.          unregister_macro (1, "_call_on_packages");
  1033.  
  1034.          // We need to search to ascii file so make it current.
  1035.          set_window (__asc_window);
  1036.          if (mark_length = search_fwd (str2, 1, 0, 0))
  1037.             {
  1038.             int   line, col;
  1039.  
  1040.             raise_anchor ();
  1041.             drop_anchor ();
  1042.             inq_position (line, col);
  1043.             next_char (mark_length);
  1044.             refresh ();
  1045.  
  1046.             // Here we want to wait for a key to show the matched
  1047.             // text highlighted.
  1048.             pause_on_error (1);
  1049.             error ("ASCII search complete - press any key.");
  1050.             pause_on_error (0);
  1051.             move_abs (line, col);
  1052.             drop_anchor (2);
  1053.             refresh ();
  1054.             set_window (__hex_window);
  1055.             raise_anchor ();
  1056.             move_abs (line, col * 2);
  1057.             move_rel (0, -1);
  1058.             drop_anchor ();
  1059.             move_rel (0, 1);
  1060.             refresh ();
  1061.             }
  1062.          else
  1063.             message ("Pattern not found");
  1064.  
  1065.          set_window (__hex_window);
  1066.          register_macro (1, "_call_on_packages");
  1067.          refresh ();
  1068.          }
  1069.       }
  1070. }
  1071. /*
  1072. ** This macro is very similar the the ascii_search macro but it uses a different
  1073. ** character delimiter regular expression and searches in the hex buffer.  Matched
  1074. ** text is highlighted with pause on error.
  1075. */
  1076. void _bin_search ()
  1077. {
  1078.    string   str1,
  1079.             str2;
  1080.  
  1081.    if (get_parm (0, str1, "Enter hex values: ", inq_line_length () / 8))
  1082.       {
  1083.       while (strlen (compress(str1)))
  1084.          {
  1085.          str2 += substr (str1, 1, 2);
  1086.          str2 += "[\n]@";
  1087.          if (substr(str1,3,1)==" ")
  1088.             str1 = substr (str1, 4);
  1089.          else
  1090.             str1 = substr (str1, 3);
  1091.          }
  1092.       if (strlen (str2))
  1093.          {
  1094.          int   mark_length,
  1095.                line,
  1096.                col;
  1097.          save_position();
  1098.          while (mark_length = search_fwd (str2, 1, 0, 0))
  1099.             {
  1100.             inq_position (line, col);
  1101.             if ((col % 2) == 0)
  1102.             {
  1103.                move_rel(0,1);
  1104.                continue;
  1105.             }
  1106.             else
  1107.                break;
  1108.             }
  1109.          if (! mark_length)
  1110.          {
  1111.             message ("Pattern not found");
  1112.             restore_position();
  1113.          }
  1114.          else
  1115.          {
  1116.             restore_position(0);
  1117.             unregister_macro (1, "_call_on_packages");
  1118.             raise_anchor ();
  1119.             move_abs (line, col);
  1120.             drop_anchor ();
  1121.             next_char (mark_length);
  1122.             refresh ();
  1123.             pause_on_error (1);
  1124.             error ("HEX search complete - press any key.");
  1125.             pause_on_error (0);
  1126.             move_abs (line, col);
  1127.             raise_anchor ();
  1128.             drop_anchor ();
  1129.             move_rel (0, 1);
  1130.             col += 1;
  1131.             col /= 2;
  1132.             set_window (__asc_window);
  1133.             raise_anchor ();
  1134.             move_abs (line, col);
  1135.             drop_anchor (2);
  1136.             refresh ();
  1137.             set_window (__hex_window);
  1138.             register_macro (1, "_call_on_packages");
  1139.  
  1140.          }
  1141.       }
  1142.    }
  1143. }
  1144. #define BTN1_CLICK     10
  1145. #define BTN2_CLICK     11
  1146. #define BTN1_DBLCLK    13
  1147. #define BTN2_DBLCLK    14
  1148. #define VSCROLL        17
  1149. #define CLOSE_WIN      19
  1150. #define SET_WIN        20
  1151. #define STATUS_AREA    21
  1152.  
  1153. #define SB_LINEUP          0
  1154. #define SB_LINEDOWN        1
  1155. #define SB_PAGEUP          2
  1156. #define SB_PAGEDOWN        3
  1157. #define SB_TOP             6
  1158. #define SB_BOTTOM          7
  1159. #define TITLE_BAR       1
  1160. /*
  1161. **    This is the mouse event handler which acknowledges the following events.
  1162. **    
  1163. **    STATUS AREA CLICK - goto offset
  1164. **    LEFT BUTTON CLICK - position the cursor
  1165. **    RIGHT BUTTON CLICK - position the cursor
  1166. **    LEFT BUTTON DOUBLE CLICK - enter ascii value
  1167. **    RIGHT BUTTON DOUBLE CLICK - open a line
  1168. **    VERTICAL SCROLL - positioning with clicks
  1169. */
  1170. void _bin_mouse(int action, int modifier, int line, int col)
  1171. {
  1172.    if (inq_window()==__asc_window)
  1173.       col=col*2;
  1174.    switch (action)
  1175.    {
  1176.       case STATUS_AREA:
  1177.          execute_macro(inq_assignment("<Alt-g>"));
  1178.       case SET_WIN:
  1179.       {
  1180.          if (col!=TITLE_BAR && line == __asc_window)
  1181.          {
  1182.             unregister_macro (1, "_call_on_packages");
  1183.             set_window (__asc_window);
  1184.          }
  1185.       }
  1186.       case BTN2_CLICK:
  1187.       case BTN2_DBLCLK:
  1188.       case BTN1_CLICK:
  1189.       case BTN1_DBLCLK:
  1190.       {
  1191.          int lines,cols;
  1192.          if (col % 2)
  1193.             col++;
  1194.          if (col>50)
  1195.             col=50;
  1196.          unregister_macro (1, "_call_on_packages");
  1197.          set_window (__hex_window);
  1198.          inq_position(lines, cols);
  1199.          raise_anchor ();
  1200.          move_rel(0,-1);
  1201.          save_position();
  1202.          if (move_abs(line,col))
  1203.          {
  1204.             if (! inq_position(lines,cols)&& lines==line && cols == col)
  1205.             {
  1206.                restore_position(0);
  1207.                move_rel(0,-1);
  1208.                set_window (__asc_window);
  1209.                raise_anchor ();
  1210.                move_abs(line,col / 2);
  1211.                drop_anchor (2);
  1212.                refresh ();
  1213.                set_window (__hex_window);
  1214.             }
  1215.             else
  1216.                restore_position();
  1217.          }
  1218.          else
  1219.             restore_position();
  1220.          drop_anchor ();
  1221.          move_rel (0, 1);
  1222.          register_macro (1, "_call_on_packages");
  1223.          refresh ();
  1224.          switch (action)
  1225.          {
  1226.             case BTN2_DBLCLK:
  1227.             {
  1228.                execute_macro(inq_assignment("<Ctrl-Enter>"));
  1229.             }
  1230.             case BTN1_DBLCLK:
  1231.             {
  1232.                string sread,
  1233.                      character;
  1234.                int hex_val;
  1235.                raise_anchor ();
  1236.                // Read the text from the buffer to display the old value at the prompt.
  1237.                move_rel (0, -1);
  1238.                sread = "Enter new value for ";
  1239.                if (read (1) != "\n")
  1240.                   sread += read (2);
  1241.                sread += ": ";
  1242.                if (get_parm (NULL, character, sread, 2))
  1243.                   // Convert the "hex" string to an integer.
  1244.                   {
  1245.                   hex_val = _bin_atoh (character);
  1246.  
  1247.                   // Convert the integer to a hex value.
  1248.                   sprintf (character, "%02x", hex_val);
  1249.  
  1250.                   unregister_macro (1, "_call_on_packages");
  1251.                   set_window (__asc_window);
  1252.  
  1253.                   // Make sure the value is insertable.
  1254.                   switch (hex_val)
  1255.                      {
  1256.                      case 13:
  1257.                      case 9:
  1258.                      case 0:
  1259.                         sread = ".";
  1260.                      default:
  1261.                         sprintf (sread, "%c", hex_val);
  1262.                      }
  1263.  
  1264.                   // Insert the value in the hex and ascii buffers rehighlight and
  1265.                   // return.
  1266.                   insert ("%s", sread);
  1267.                   raise_anchor ();
  1268.                   delete_char ();
  1269.                   move_rel (0, -1);
  1270.                   drop_anchor (2);
  1271.                   refresh ();
  1272.                   set_window (__hex_window);
  1273.                   insert ("%s", upper (character));
  1274.                   delete_char (2);
  1275.                   move_rel (0, -2);
  1276.                   }
  1277.                drop_anchor ();
  1278.                move_rel (0, 1);
  1279.                refresh ();
  1280.                register_macro (1, "_call_on_packages");
  1281.                refresh ();
  1282.                _bin_disp_offset ();
  1283.  
  1284.             }
  1285.          }
  1286.       }
  1287.       case VSCROLL:
  1288.       {
  1289.          switch (line)
  1290.          {
  1291.             case SB_LINEUP:
  1292.                execute_macro(inq_assignment("<Left>"));
  1293.             case SB_LINEDOWN:
  1294.                execute_macro(inq_assignment("<Right>"));
  1295.             case SB_PAGEUP:
  1296.                execute_macro(inq_assignment("<PgUp>"));
  1297.             case SB_PAGEDOWN:
  1298.                execute_macro(inq_assignment("<PgDn>"));
  1299.             case SB_TOP:
  1300.                execute_macro(inq_assignment("<Ctrl-PgUp>"));
  1301.             case SB_BOTTOM:
  1302.                execute_macro(inq_assignment("<Ctrl-PgDn>"));
  1303.          }
  1304.       }
  1305.    }
  1306. }
  1307.  
  1308. #endif
  1309. #ifdef UNIX
  1310. // This macro associates a system buffer with a unix buffer name.
  1311. void _unx_edit (string file_name)
  1312. {
  1313.    int   unix_buffer,
  1314.          tmp_buf,
  1315.          current_buffer;
  1316.  
  1317.    string   buffer_name,
  1318.             file_ext,
  1319.             buffer_id,
  1320.             file_path;
  1321.  
  1322.    // Get the file name
  1323.    if (get_parm (0, file_name))
  1324.       {
  1325.       // Parse the file name into path and extension
  1326.       if (index (file_name, "."))
  1327.          {
  1328.          file_ext = substr (file_name, 1 + rindex (file_name, "."));
  1329.          file_name = substr (file_name, 1, rindex (file_name, ".") - 1);
  1330.          }
  1331.       else
  1332.          file_ext = "";
  1333.       // Parse off the path for the buffer name
  1334.       buffer_name = substr (file_name, rindex (file_name, "\\") + 1);
  1335.  
  1336.       // Store the current id to possible deletion
  1337.       current_buffer = inq_buffer ();
  1338.  
  1339.       // Try to create the buffer to check for existing buffer id
  1340.       tmp_buf = create_buffer (buffer_name + "." + file_ext, file_name + ".unx", 0);
  1341.  
  1342.       // If a valid buffer exists, continue
  1343.       if (tmp_buf)
  1344.          // Delete the current buffer
  1345.          {
  1346.          delete_buffer (current_buffer);
  1347.  
  1348.          // See if the unix file is already being edited
  1349.          set_buffer (__unix_files);
  1350.          top_of_buffer ();
  1351.          if (search_fwd (file_name + ",", 0, 0))
  1352.  
  1353.             // The unix file is being edited called edit_file and return
  1354.             edit_file (file_name + ".unx");
  1355.          else
  1356.             // It's a new conversion delete the validity check buffer
  1357.             {
  1358.             delete_buffer (tmp_buf);
  1359.  
  1360.             // Create the dos string from the file name
  1361.             sprintf (file_path, "bbe UD %s.%s %s.unx>&nul", file_name, file_ext, file_name);
  1362.  
  1363.             // Does the file exist?
  1364.             if (exist ((file_name + ".") + file_ext))
  1365.                // Do the .unx files already exist?
  1366.                {
  1367.                if (!exist (file_name + ".unx"))
  1368.                   // Call dos for the conversion
  1369.                   {
  1370.                   message ("Generating dos equivalent of %s.%s", file_name,file_ext);
  1371.                   dos (file_path);
  1372.                   }
  1373.                else
  1374.                   message ("Editing existing files.");
  1375.                // Edit the converted file
  1376.                unix_buffer = create_buffer (buffer_name + ("." + file_ext), file_name + ".unx", 0);
  1377.  
  1378.                // Save the true filename in the unix_files system
  1379.                // buffer for later.
  1380.                sprintf (buffer_id, "file=%s,ext=%s", file_name, file_ext);
  1381.                set_buffer (__unix_files);
  1382.                beginning_of_line ();
  1383.                insert (buffer_id + "\n");
  1384.  
  1385.                set_buffer (unix_buffer);
  1386.                top_of_buffer ();
  1387.                switch (file_ext)
  1388.                   {
  1389.                   case "c":
  1390.                   case "cb":
  1391.                   case "cpp":
  1392.                   case "h":
  1393.                   case "hpp":
  1394.                       .c_template_first (1, 1, 0, 1);
  1395.                   case "for":
  1396.                       .for_template_first (0, 2, 1, 1);
  1397.                   case "ada":
  1398.                       .ada_template_first (1, 0);
  1399.                   case "mod":
  1400.                   case "def":
  1401.                       .mod_template_first (1, 0, 0, 1);
  1402.                   case "prg":
  1403.                   case "tem":
  1404.                   case "pre":
  1405.                       .prg_smart_first ();
  1406.                   case "for":
  1407.                       .for_template_first (0, 2, 1);
  1408.                   case "pas":
  1409.                       .pas_template_first (1, 0, 1, 1, 1);
  1410.                   case "bas":
  1411.                       .bas_template_first (1, 0, 0, 1);
  1412.                   case "cob":
  1413.                   case "cbl":
  1414.                       .cob_template_first (0, 0, 1, 1, 1);
  1415.                   default:
  1416.                       _regular_first ();
  1417.                   }
  1418.                }
  1419.             else
  1420.                message ("File %s not found", (file_name + ".") + file_ext);
  1421.             }
  1422.          }
  1423.       }
  1424. }
  1425.  
  1426. // Registered macro for trapping long lines i.e no CR/LF.
  1427. void _unix_edit ()
  1428. {
  1429.    if (inq_message () != "Null characters in file fixed." && inq_message () != "Generating hex file")
  1430.    {
  1431.       drop_anchor (3);
  1432.       if (!search_fwd ("\n", 1, 0, 1))
  1433.       {
  1434.          string   okay,
  1435.                   file;
  1436.  
  1437.          int   line_no;
  1438.  
  1439.          raise_anchor ();
  1440.          inq_names (file);
  1441.          end_of_buffer ();
  1442.          inq_position (line_no);
  1443.          if (2 >= line_no)
  1444.             // See if the conversion is requested.
  1445.             if (get_parm (0, okay, "Create file with CR/LF as EOL terminator? ", 1, "Y"))
  1446.                if (upper (okay) == "Y")
  1447.                {
  1448.                   top_of_buffer();
  1449.                   // Call _hex_edit to do the dirty work.
  1450.                   _unx_edit (file);
  1451.                }
  1452.                // Otherwise, let the user frustrate themselves.
  1453.                else
  1454.                   message ("You asked for it.");
  1455.  
  1456.          // Otherwise, return to the top of the buffer
  1457.             else ;
  1458.          else
  1459.             top_of_buffer ();
  1460.       }
  1461.       else
  1462.          beginning_of_line ();
  1463.       raise_anchor ();
  1464.    }
  1465. }
  1466. #endif
  1467.