home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / Epoc / Palmtime / files / FrotzS5_src.ZIP / S5input.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-11  |  16.8 KB  |  819 lines

  1. /*
  2.  * file "S5input.c"
  3.  *
  4.  * Borland C front end, input functions
  5.  *
  6.  */
  7.  
  8. #include "frotz.h"
  9. #include "S5frotz.h"
  10. #include "S5api.h"
  11. #include "frotzs5.h"
  12.  
  13. #ifndef HISTORY_BUFSIZE
  14. #define HISTORY_BUFSIZE 500
  15. #endif
  16.  
  17. extern short is_terminator (struct sg *g, short);
  18.  
  19. extern short read_yes_or_no (struct sg *g, const char *);
  20. extern void read_string (struct sg *g, short, zchar *);
  21.  
  22. extern short completion (struct sg *g, const zchar *, zchar *);
  23.  
  24. /*
  25.  * switch_cursor
  26.  *
  27.  * Turn cursor on/off. If there is mouse support then turn the mouse
  28.  * pointer on/off as well. The cursor should not be moved and the
  29.  * contents of the screen should not be changed while the cursor is
  30.  * visible (because of the primitive cursor emulation we use here).
  31.  *
  32.  */
  33.  
  34. void switch_cursor (struct sg *g, short cursor)
  35. {
  36.     SrvSwitchCursor(g,cursor);
  37. }/* switch_cursor */
  38.  
  39. /*
  40.  * get_key
  41.  *
  42.  * Read a keypress or a mouse click. Returns...
  43.  *
  44.  *    ZC_TIME_OUT = time limit exceeded,
  45.  *    ZC_BACKSPACE = the backspace key,
  46.  *    ZC_RETURN = the return key,
  47.  *    ZC_HKEY_MIN...ZC_HKEY_MAX = a hot key,
  48.  *    ZC_ESCAPE = the escape key,
  49.  *    ZC_ASCII_MIN...ZC_ASCII_MAX = ASCII character,
  50.  *    ZC_ARROW_MIN...ZC_ARROW_MAX = an arrow key,
  51.  *    ZC_FKEY_MIN...ZC_FKEY_MAX = a function key,
  52.  *    ZC_NUMPAD_MIN...ZC_NUMPAD_MAX = a number pad key,
  53.  *    ZC_SINGLE_CLICK = single mouse click,
  54.  *    ZC_DOUBLE_CLICK = double mouse click,
  55.  *    ZC_LATIN1_MIN+1...ZC_LATIN1_MAX = ISO Latin-1 character,
  56.  *    SPECIAL_KEY_MIN...SPECIAL_KEY_MAX = a special editing key.
  57.  *
  58.  */
  59.  
  60. short get_key (struct sg *g, short cursor)
  61. {
  62.     unsigned short key;
  63.  
  64.     /* Loop until a key was pressed */
  65.  
  66.     if (cursor)
  67.       switch_cursor (g,TRUE);
  68.  
  69.     for(;;)  {
  70.         key = SrvGetTimedCh(g,g->keytimeout);
  71.         if(key == 0)
  72.                 break;
  73.         if(key == 0x7F)
  74.           key = SPECIAL_KEY_DELETE;
  75.         if (key >= ZC_ASCII_MIN && key <= ZC_ASCII_MAX)
  76.                 break;
  77.         if (key >= ZC_LATIN1_MIN && key <= ZC_LATIN1_MAX)
  78.                 break;
  79.         if(key == ZC_INDENT)
  80.                 break;
  81.         if (key == ZC_BACKSPACE)
  82.                 break;
  83.         if (key == ZC_RETURN)
  84.                 break;
  85.         if (key == ZC_ESCAPE)
  86.                 break;
  87.         // EPOC cursor keys are translated to Frotz values as these
  88.         // are sometimes handled directly by the interpreter
  89.         if (key == ZC_EPOC_UP) {
  90.             key = ZC_ARROW_UP;
  91.             break;
  92.         }
  93.         if (key == ZC_EPOC_DOWN) {
  94.             key = ZC_ARROW_DOWN;
  95.             break;
  96.         }
  97.         if (key == ZC_EPOC_LEFT) {
  98.             key = ZC_ARROW_LEFT;
  99.             break;
  100.         }
  101.         if (key == ZC_EPOC_RIGHT) {
  102.             key = ZC_ARROW_RIGHT;
  103.             break;
  104.         }
  105.         if (key == SPECIAL_KEY_PAGE_UP) {
  106.             key = ZC_ARROW_UP;
  107.             break;
  108.         }
  109.         if (key == SPECIAL_KEY_PAGE_DOWN) {
  110.             key = ZC_ARROW_DOWN;
  111.             break;
  112.         }
  113.         if (key >= SPECIAL_KEY_MIN && key <= SPECIAL_KEY_MAX)
  114.                 break;
  115.         switch(key)
  116.           {
  117.           case 18: case 16:
  118.           case 19: case 21:
  119.           case 14: case 24:
  120.           case 4:  goto hotkey;
  121.           default:break;
  122.           }
  123.         }
  124.  
  125. hotkey:    if(key == 0)
  126.           key = ZC_TIME_OUT;
  127.  
  128.     if (cursor)
  129.       switch_cursor (g,FALSE);
  130.  
  131.     return key;
  132.  
  133. }/* get_key */
  134.  
  135. /*
  136.  * cursor_left
  137.  *
  138.  * Move the cursor one character to the left.
  139.  *
  140.  */
  141.  
  142. void cursor_left (struct sg *g)
  143. {
  144.  
  145.     if (g->input.pos > 0)
  146.     {
  147.         g->input.pos--;
  148.         SrvSetCursor(g,--g->cursor_x, g->cursor_y);
  149.     }
  150. }/* cursor_left */
  151.  
  152. /*
  153.  * cursor_right
  154.  *
  155.  * Move the cursor one character to the right.
  156.  *
  157.  */
  158.  
  159. void cursor_right (struct sg *g)
  160. {
  161.  
  162.     if (g->input.pos < g->input.length)
  163.     {
  164.         g->input.pos++;
  165.         SrvSetCursor(g,++g->cursor_x, g->cursor_y);
  166.     }
  167.  
  168. }/* cursor_right */
  169.  
  170. /*
  171.  * first_char
  172.  *
  173.  * Move the cursor to the beginning of the input line.
  174.  *
  175.  */
  176.  
  177. void first_char (struct sg *g)
  178. {
  179.  
  180.     while (g->input.pos > 0)
  181.     cursor_left (g);
  182.  
  183. }/* first_char */
  184.  
  185. /*
  186.  * last_char
  187.  *
  188.  * Move the cursor to the end of the input line.
  189.  *
  190.  */
  191.  
  192. void last_char (struct sg *g)
  193. {
  194.  
  195.     while (g->input.pos < g->input.length)
  196.     cursor_right (g);
  197.  
  198. }/* last_char */
  199.  
  200. /*
  201.  * prev_word
  202.  *
  203.  * Move the cursor to the start of the previous word.
  204.  *
  205.  */
  206.  
  207. void prev_word (struct sg *g)
  208. {
  209.  
  210.     do {
  211.  
  212.     cursor_left (g);
  213.  
  214.     if (g->input.pos == 0)
  215.         return;
  216.  
  217.     } while (g->input.buffer[g->input.pos] == ' ' || g->input.buffer[g->input.pos - 1] != ' ');
  218.  
  219. }
  220.  
  221. /* prev_word */
  222.  
  223. /*
  224.  * next_word
  225.  *
  226.  * Move the cursor to the start of the next word.
  227.  *
  228.  */
  229.  
  230. void next_word (struct sg *g)
  231. {
  232.  
  233.     do {
  234.  
  235.     cursor_right (g);
  236.  
  237.     if (g->input.pos == g->input.length)
  238.         return;
  239.  
  240.     } while (g->input.buffer[g->input.pos] == ' ' || g->input.buffer[g->input.pos - 1] != ' ');
  241.  
  242. }
  243.  
  244. /* next_word */
  245.  
  246. /*
  247.  * input_move
  248.  *
  249.  * Helper function to move parts of the input buffer:
  250.  *
  251.  *    newc != 0, oldc == 0: INSERT
  252.  *    newc != 0, oldc != 0: OVERWRITE
  253.  *    newc == 0, oldc != 0: DELETE
  254.  *    newc == 0, oldc == 0: NO OPERATION
  255.  *
  256.  */
  257.  
  258. #define H(x) (x ? 1 : 0)
  259.  
  260. void input_move (struct sg *g, zchar newc, zchar oldc)
  261. {
  262.     short newwidth = (newc != 0) ? 1 : 0;
  263.     short oldwidth = (oldc != 0) ? 1 : 0;
  264.  
  265.     zchar *p = g->input.buffer + g->input.pos;
  266.  
  267.     short saved_x = g->cursor_x;
  268.  
  269.     short updated_width = g->input.width + newwidth - oldwidth;
  270.     short updated_length = g->input.length + H (newc) - H (oldc);
  271.  
  272.     if (updated_width > g->input.max_width)
  273.     return;
  274.     if (updated_length > g->input.max_length)
  275.     return;
  276.  
  277.     g->input.width = updated_width;
  278.     g->input.length = updated_length;
  279.  
  280.     if (oldc != 0 && newc == 0)
  281.     Srvmemmove (p, p + 1, updated_length - g->input.pos + 1);
  282.     if (newc != 0 && oldc == 0)
  283.     Srvmemmove (p + 1, p, updated_length - g->input.pos);
  284.  
  285.     if (newc != 0)
  286.     *p = newc;
  287.  
  288.     os_display_string (g,p);
  289.  
  290.     switch_scrn_attr (g,TRUE);
  291.  
  292.     if (oldwidth > newwidth)
  293.  
  294.     os_erase_area (g,
  295.         g->cursor_y + 1,
  296.         g->cursor_x + 1,
  297.         g->cursor_y + g->h_font_height,
  298.         g->cursor_x + oldwidth - newwidth);
  299.  
  300.     switch_scrn_attr (g,FALSE);
  301.  
  302.     g->cursor_x = saved_x;
  303.  
  304.     if (newc != 0)
  305.     cursor_right (g);
  306.  
  307. }/* input_move */
  308.  
  309. //#undef H(x)
  310.  
  311. /*
  312.  * delete_char
  313.  *
  314.  * Delete the character below the cursor.
  315.  *
  316.  */
  317.  
  318. void delete_char (struct sg *g)
  319. {
  320.  
  321.     input_move (g,0, g->input.buffer[g->input.pos]);
  322.     SrvSetCursor(g,g->cursor_x, g->cursor_y);
  323.  
  324. }/* delete_char */
  325.  
  326. /*
  327.  * delete_left
  328.  *
  329.  * Delete the character to the left of the cursor.
  330.  *
  331.  */
  332.  
  333. void delete_left (struct sg *g)
  334. {
  335.  
  336.     if (g->input.pos > 0) {
  337.     cursor_left (g);
  338.     delete_char (g);
  339.     }
  340.  
  341. }/* delete_left */
  342.  
  343. /*
  344.  * truncate_line
  345.  *
  346.  * Truncate the input line to n characters.
  347.  *
  348.  */
  349.  
  350. void truncate_line (struct sg *g, short n)
  351. {
  352.  
  353.     last_char (g);
  354.  
  355.     while (g->input.length > n)
  356.     delete_left (g);
  357.  
  358. }/* truncate_line */
  359.  
  360. /*
  361.  * insert_char
  362.  *
  363.  * Insert a character into the input buffer.
  364.  *
  365.  */
  366.  
  367. void insert_char (struct sg *g, zchar newc)
  368. {
  369.     zchar oldc = 0;
  370.  
  371.     if (g->overwrite)
  372.     oldc = g->input.buffer[g->input.pos];
  373.  
  374.     input_move (g,newc, oldc);
  375.  
  376. }/* insert_char */
  377.  
  378. /*
  379.  * insert_string
  380.  *
  381.  * Add a string of characters to the input line.
  382.  *
  383.  */
  384.  
  385. void insert_string (struct sg *g, const zchar *s)
  386. {
  387.  
  388.     while (*s != 0) {
  389.  
  390.     if (g->input.length + 1 > g->input.max_length)
  391.         break;
  392.     if (g->input.width + 1 > g->input.max_width)
  393.         break;
  394.  
  395.     insert_char (g,*s++);
  396.  
  397.     }
  398.  
  399. }/* insert_string */
  400.  
  401. /*
  402.  * tabulator_key
  403.  *
  404.  * Complete the word at the end of the input line, if possible.
  405.  *
  406.  */
  407.  
  408. void tabulator_key (struct sg *g)
  409. {
  410.     short status;
  411.  
  412.     if (g->input.pos == g->input.length) {
  413.  
  414.     zchar extension[10];
  415.  
  416.     status = completion (g,g->input.buffer, extension);
  417.     insert_string (g,extension);
  418.  
  419.     } else status = 2;
  420.  
  421.     /* Beep if the completion was impossible or ambiguous */
  422.  
  423. }/* tabulator_key */
  424.  
  425. /*
  426.  * store_input
  427.  *
  428.  * Copy the current input line to the history buffer.
  429.  *
  430.  */
  431.  
  432. void store_input (struct sg *g)
  433. {
  434.  
  435.     if (g->input.length >= HISTORY_MIN_ENTRY) {
  436.  
  437.     const zchar *ptr = g->input.buffer;
  438.  
  439.     do {
  440.  
  441.         if (g->history.latest++ == HISTORY_BUFSIZE - 1)
  442.         g->history.latest = 0;
  443.  
  444.         g->history.buffer[g->history.latest] = *ptr;
  445.  
  446.     } while (*ptr++ != 0);
  447.  
  448.     }
  449.  
  450. }/* store_input */
  451.  
  452. /*
  453.  * fetch_entry
  454.  *
  455.  * Copy the current history entry to the input buffer and check if it
  456.  * matches the prefix in the input buffer.
  457.  *
  458.  */
  459.  
  460. short fetch_entry (struct sg *g, zchar *buf, short entry)
  461. {
  462.     short i = 0;
  463.  
  464.     zchar c;
  465.  
  466.     do {
  467.  
  468.     if (entry++ == HISTORY_BUFSIZE - 1)
  469.         entry = 0;
  470.  
  471.     c = g->history.buffer[entry];
  472.  
  473.     if (i < g->history.prefix_len && g->input.buffer[i] != c)
  474.         return FALSE;
  475.  
  476.     buf[i++] = c;
  477.  
  478.     } while (c != 0);
  479.  
  480.     return (i > g->history.prefix_len) && (i > 1);
  481.  
  482. }/* fetch_entry */
  483.  
  484. /*
  485.  * get_prev_entry
  486.  *
  487.  * Copy the previous history entry to the input buffer.
  488.  *
  489.  */
  490.  
  491. void get_prev_entry (struct sg *g)
  492. {
  493.     zchar buf[INPUT_BUFFER_SIZE];
  494.  
  495.     short i = g->history.current;
  496.  
  497.     do {
  498.  
  499.     do {
  500.  
  501.         if (i-- == 0)
  502.         i = HISTORY_BUFSIZE - 1;
  503.  
  504.         if (i == g->history.latest)
  505.         return;
  506.  
  507.     } while (g->history.buffer[i] != 0);
  508.  
  509.     } while (!fetch_entry (g,buf, i));
  510.  
  511.     truncate_line (g,g->history.prefix_len);
  512.  
  513.     insert_string (g,buf + g->history.prefix_len);
  514.  
  515.     g->history.current = i;
  516.  
  517. }/* get_prev_entry */
  518.  
  519. /*
  520.  * get_next_entry
  521.  *
  522.  * Copy the next history entry to the input buffer.
  523.  *
  524.  */
  525.  
  526. void get_next_entry (struct sg *g)
  527. {
  528.     zchar buf[INPUT_BUFFER_SIZE];
  529.  
  530.     short i = g->history.current;
  531.  
  532.     truncate_line (g,g->history.prefix_len);
  533.  
  534.     do {
  535.  
  536.     do {
  537.  
  538.         if (i == g->history.latest)
  539.         return;
  540.  
  541.         if (i++ == HISTORY_BUFSIZE - 1)
  542.         i = 0;
  543.  
  544.     } while (g->history.buffer[i] != 0);
  545.  
  546.     if (i == g->history.latest)
  547.         goto no_further;
  548.  
  549.     } while (!fetch_entry (g,buf, i));
  550.  
  551.     insert_string (g,buf + g->history.prefix_len);
  552.  
  553. no_further:
  554.  
  555.     g->history.current = i;
  556.  
  557. }/* get_next_entry */
  558.  
  559. /*
  560.  * os_read_line
  561.  *
  562.  * Read a line of input from the keyboard into a buffer. The buffer
  563.  * may already be primed with some text. In this case, the "initial"
  564.  * text is already displayed on the screen. After the input action
  565.  * is complete, the function returns with the terminating key value.
  566.  * The length of the input should not exceed "max" characters plus
  567.  * an extra 0 terminator.
  568.  *
  569.  * Terminating keys are the return key (13) and all function keys
  570.  * (see the Specification of the Z-machine) which are accepted by
  571.  * the is_terminator function. Mouse clicks behave like function
  572.  * keys except that the mouse position is stored in global variables
  573.  * "mouse_x" and "mouse_y" (top left coordinates are (1,1)).
  574.  *
  575.  * Furthermore, Frotz introduces some special terminating keys:
  576.  *
  577.  *     ZC_HKEY_PLAYBACK (Alt-P)
  578.  *     ZC_HKEY_RECORD (Alt-R)
  579.  *     ZC_HKEY_SEED (Alt-S)
  580.  *     ZC_HKEY_UNDO (Alt-U)
  581.  *     ZC_HKEY_RESTART (Alt-N, "new game")
  582.  *     ZC_HKEY_QUIT (Alt-X, "exit game")
  583.  *     ZC_HKEY_DEBUGGING (Alt-D)
  584.  *     ZC_HKEY_HELP (Alt-H)
  585.  *
  586.  * If the timeout argument is not zero, the input gets interrupted
  587.  * after timeout/10 seconds (and the return value is 0).
  588.  *
  589.  * The complete input line including the cursor must fit in "width"
  590.  * screen units.
  591.  *
  592.  * The function may be called once again to continue after timeouts,
  593.  * misplaced mouse clicks or hot keys. In this case the "continued"
  594.  * flag will be set. This information can be useful if the interface
  595.  * implements input line history.
  596.  *
  597.  * The screen is not scrolled after the return key was pressed. The
  598.  * cursor is at the end of the input line when the function returns.
  599.  *
  600.  * Since Inform 2.2 the helper function "completion" can be called
  601.  * to implement word completion (similar to tcsh under Unix).
  602.  *
  603.  */
  604.  
  605. #define new_history_search() \
  606.     { g->history.prefix_len = g->input.pos; g->history.current = g->history.latest; }
  607.  
  608. zchar os_read_line (struct sg *g, short max, zchar *buf, short timeout, short width, short continued)
  609. {
  610.     short key = continued ? 9999 : 0;
  611.  
  612.     /* Initialise input variables */
  613.     g->input.buffer = buf;
  614.     g->input.pos = Srvstrlen ((char *) buf);
  615.     g->input.length = Srvstrlen ((char *) buf);
  616.     g->input.max_length = max;
  617.     g->input.width = os_string_width (g,buf);
  618.     g->input.max_width = width - 1;
  619.  
  620.     /* Calculate time limit */
  621.  
  622.     g->keytimeout = timeout;
  623.  
  624.     /* Loop until a terminator is found */
  625.  
  626.     do {
  627.  
  628.         if (key != 9999)
  629.             new_history_search ();
  630.  
  631.         /* Get next key from mouse or keyboard */
  632.  
  633.         key = get_key (g,TRUE);
  634.  
  635.         if (key < ZC_ASCII_MIN || key > ZC_ASCII_MAX && key < ZC_LATIN1_MIN || key > ZC_LATIN1_MAX) {
  636.  
  637.             /* Ignore time-outs if the cursor is not at end of the line */
  638.  
  639.             if (key == ZC_TIME_OUT && g->input.pos < g->input.length)
  640.                 key = 9999;
  641.  
  642.             /* Backspace, return and escape keys */
  643.  
  644.             if (key == ZC_BACKSPACE)
  645.                 delete_left (g);
  646.             if (key == ZC_RETURN)
  647.                 store_input (g);
  648.             if (key == ZC_ESCAPE)
  649.                 truncate_line (g,0);
  650.  
  651.             /* Editing keys */
  652.  
  653.             if (g->cwin == 0) {
  654.  
  655.                 if (key == ZC_ARROW_UP)
  656.                     get_prev_entry (g);
  657.                 if (key == ZC_ARROW_DOWN)
  658.                     get_next_entry (g);
  659.                 if (key == ZC_ARROW_LEFT)
  660.                     cursor_left (g);
  661.                 if (key == ZC_ARROW_RIGHT)
  662.                     cursor_right (g);
  663.                 if (key == ZC_INDENT)
  664.                     tabulator_key (g);
  665.  
  666.                 // Test for all 4 cursor keys
  667.                 if (key >= ZC_ARROW_MIN && key <= ZC_ARROW_MAX)
  668.                     key = 9999;
  669.  
  670.                 if (key == SPECIAL_KEY_HOME)
  671.                     first_char (g);
  672.                 if (key == SPECIAL_KEY_END)
  673.                     last_char (g);
  674.                 if (key == SPECIAL_KEY_DELETE)
  675.                     delete_char (g);
  676.                 if (key == SPECIAL_KEY_WORD_LEFT)
  677.                     prev_word (g);
  678.                 if (key == SPECIAL_KEY_WORD_RIGHT)
  679.                     next_word (g);
  680.                 /*if (key == SPECIAL_KEY_INSERT)
  681.                     overwrite = !overwrite;*/
  682.  
  683.             }
  684.  
  685.         } else insert_char (g,(unsigned char)key);
  686.  
  687.     } while (key > 0xff || !is_terminator (g,key));
  688.  
  689.     last_char (g);
  690.  
  691.     g->overwrite = FALSE;
  692.  
  693.     /* Return terminating key */
  694.  
  695.     return (unsigned char)key;
  696.  
  697. }/* os_read_line */
  698.  
  699. //#undef new_history_search()
  700.  
  701. /*
  702.  * os_read_key
  703.  *
  704.  * Read a single character from the keyboard (or a mouse click) and
  705.  * return it. Input aborts after timeout/10 seconds.
  706.  *
  707.  */
  708.  
  709. zchar os_read_key (struct sg *g, short timeout, short cursor)
  710. {
  711.     short key;
  712.  
  713.     g->keytimeout = timeout;
  714.  
  715.     do {
  716.  
  717.     key = get_key (g,cursor);
  718.  
  719.     } while (key > 0xff);
  720.  
  721.     return (unsigned char)key;
  722.  
  723. }/* os_read_key */
  724.  
  725. /*
  726.  * os_read_file_name
  727.  *
  728.  * Return the name of a file. Flag can be one of:
  729.  *
  730.  *    FILE_SAVE     - Save game file
  731.  *    FILE_RESTORE  - Restore game file
  732.  *    FILE_SCRIPT   - Transscript file
  733.  *    FILE_RECORD   - Command file for recording
  734.  *    FILE_PLAYBACK - Command file for playback
  735.  *    FILE_SAVE_AUX - Save auxilary ("preferred settings") file
  736.  *    FILE_LOAD_AUX - Load auxilary ("preferred settings") file
  737.  *
  738.  * The length of the file name is limited by MAX_FILE_NAME. Ideally
  739.  * an interpreter should open a file requester to ask for the file
  740.  * name. If it is unable to do that then this function should call
  741.  * print_string and read_string to ask for a file name.
  742.  *
  743.  */
  744.  
  745. short os_read_file_name (struct sg *g, char *file_name, const char *default_name, short flag)
  746. {
  747.     char *extension;
  748. //    FILE *fp;
  749.     short result;
  750.  
  751.     short saved_replay = g->istream_replay;
  752.     short saved_record = g->ostream_record;
  753.  
  754.     /* Turn off playback and recording temporarily */
  755.  
  756.     g->istream_replay = FALSE;
  757.     g->ostream_record = FALSE;
  758.  
  759.     /* Select appropriate extension */
  760.  
  761.     extension = ".aux";
  762.  
  763.     if (flag == FILE_SAVE || flag == FILE_RESTORE)
  764.     extension = ".sav";
  765.     if (flag == FILE_SCRIPT)
  766.     extension = ".scr";
  767.     if (flag == FILE_RECORD || flag == FILE_PLAYBACK)
  768.     extension = ".rec";
  769.  
  770.     /* Input file name (reserve four bytes for a file name extension) */
  771.  
  772. /*    print_string ("Enter file name (\"");
  773.     print_string (extension);
  774.     print_string ("\" will be added).\nDefault is \"");
  775.     print_string (default_name);
  776.     print_string ("\": ");
  777.  
  778.     read_string (MAX_FILE_NAME - 4, (zchar *) file_name);*/
  779.     Srvstrcpy(file_name,default_name);
  780.     if (flag == FILE_SAVE || flag == FILE_RECORD || flag == FILE_SAVE_AUX)
  781.     {
  782.     if(!SrvDlgSave(g,((CFrotzAppUi *)(g->papp))->savepath, file_name))
  783.       {
  784.       result = FALSE;
  785.       goto finished;
  786.       }
  787.     }
  788.     else
  789.     {
  790.     if(!SrvDlgOpen(g,((CFrotzAppUi *)(g->papp))->savepath, file_name))
  791.       {
  792.       result = FALSE;
  793.       goto finished;
  794.       }
  795.     }
  796.  
  797.     /* Use the default name if nothing was typed */
  798.  
  799.     /*if (file_name[0] == 0)
  800.     Srvstrcpy (file_name, default_name);
  801.     if (Srvstrchr (file_name, '.') == NULL)
  802.     Srvstrcat (file_name, extension);*/
  803.  
  804.     /* Make sure it is safe to use this file name */
  805.  
  806.     result = TRUE;
  807.  
  808.  
  809. finished:
  810.  
  811.     /* Restore state of playback and recording */
  812.  
  813.     g->istream_replay = saved_replay;
  814.     g->ostream_record = saved_record;
  815.  
  816.     return result;
  817.  
  818. }/* os_read_file_name */
  819.