home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 16 / 16.iso / w / w055 / 4.ddi / SOURCES.LIF / WINDOWS.PEL < prev    next >
Encoding:
Text File  |  1990-09-27  |  30.3 KB  |  1,177 lines

  1. # $Header:   P:/source/ppee/macros/windows.pev   1.110   26 Sep 1990 17:04:58   skipr  $
  2.  
  3. ##############################################################################
  4. #
  5. #           Sage Software - POLYTRON Division
  6. #             1700 NW 167th Place
  7. #               Beaverton, OR 97006
  8. #
  9. #   Copyright 1990, Sage Software, Inc.
  10. #
  11. #   Permission is hereby granted for licensed users of Sage Professional
  12. #   Editor and PolyAwk to copy and modify this source code for their own
  13. #   personal use.  These derivative works may be distributed only to other
  14. #   licensed Sage Professional Editor and PolyAwk users.  All other usage
  15. #   is prohibited without express written permission from Sage Software.
  16. #
  17. ##############################################################################
  18.  
  19. #### $Workfile:   windows.pel  $: support for windows
  20.  
  21. #### symbolic window flag values
  22. #
  23. global    WINDOW_COLLAPSED= 0x0000 # window collapsed
  24. global    WINDOW_NORMAL    = 0x0001 # window normal
  25. global    WINDOW_EXPANDED    = 0x0002 # window expanded
  26. global    WINDOW_HIDDEN    = 0x0003 # window state: one of the above
  27. global    WINDOW_ZOOM    = 0x0003 # window state: one of the above
  28.  
  29. global    WINDOW_SYSTEM    = 0x0004 # window is a "system" window
  30.  
  31. global    WINDOW_BORDERS    = 0x00F0 # all border & scroll-bar bits (for toggle_borders)
  32. global    WINDOW_BORDER    = 0x0080 # border present w/out scroll-bars (used for Menus)
  33. global    WINDOW_SB_RIGHT    = 0x0010 # border w/scroll bar right
  34. global    WINDOW_SB_BELOW    = 0x0020 # border w/scroll bar below
  35. global    WINDOW_SB_LEFT    = 0x0040 # border w/scroll bar left
  36.  
  37. global    WINDOW_CHARS    = 0x0300 # character mapping bits
  38. global    WINDOW_IBM    = 0x0000 # non-ascii as IBM chars
  39. global    WINDOW_OCTAL    = 0x0100 # non-ascii as OCTAL
  40. global    WINDOW_HEX    = 0x0200 # non-ascii as HEX
  41.                  # (if both HEX and OCTAL are specified,
  42.                  #  result is UNDEFINED (currently it is
  43.                  #  the same as if neither is specified))
  44.  
  45. global    WINDOW_CARAT    = 0x0800 # display control chars as ^X
  46.  
  47. global    WINDOW_TITLEA    = 0x1000 # title bar above/top of window
  48. global    WINDOW_TITLEB    = 0x2000 # title bar below/bottom of window
  49.                  # (TITLEB is ignored if TITLEA or if
  50.                  #  SB_BELOW are specified)
  51. global    WINDOW_TITLE    = 0x3000 # title bar above/top of window
  52.  
  53. global    WINDOW_RULER    = 0x4000 # visible tab ruler
  54.  
  55. global    WINDOW_HEADERS    = 0x7000 # titles and tab ruler
  56.  
  57.  
  58. # some useful combinations:
  59.  
  60. global WINDOW_NOBORDER    = 0x0000 # no border, no title, no nothing
  61. global WINDOW_NOTITLE    = 0x0000 # no title
  62. global WINDOW_STANDARD    = 0x1090 # title and border w/scroll bar right (SPE default)
  63. global WINDOW_PLAIN    = 0x1080 # title and plain border (Brief default)
  64. global WINDOW_SB_RIGHTB    = 0x0030 # border w/scroll bar right & below
  65. global WINDOW_SB_LEFTB    = 0x0060 # border w/scroll bar left & below
  66. global WINDOW_MENU    = 0x1084 # system window w/ title, plain border
  67. global WINDOW_MENU0    = 0x0084 # system window w/ plain border, no title
  68.  
  69. # user definable window flags
  70. global    DOS_WINDOW_FLAG = 0x00020000;
  71.  
  72. # System primitives allow windows as small as 1x1.
  73. # This package enforces a larger minimum window size:
  74.  
  75. global WINDOW_MIN_WIDTH = 12
  76. global WINDOW_MIN_HEIGHT = 2
  77.  
  78.  
  79. #--------------------------------------------------------------
  80. # Windows
  81. #--------------------------------------------------------------
  82.  
  83. ### window creation/deletion
  84.  
  85. ### create a window, using mouse if enabled, otherwise keyboard
  86. #
  87.  
  88. function make_window(){                        #PUBLIC #VOID
  89.     if( mouse_enabled && mouse_available ) {
  90.         current_window = create_window()
  91.         attach_window_buffer( current_window, current_buffer )
  92.         color_current_window()        # maybe change its color
  93.     } else {
  94.         current_window = create_medium_window()
  95.         attach_window_buffer( current_window, current_buffer )
  96.         adjust_window()
  97.     }
  98. }
  99.  
  100. ### create a window, with all per-window attributes set to "standard" values
  101. #
  102. #    an optional fifth argument sets the window flags
  103. #
  104. #    this code can generate 2 window-changed events because
  105. #    the new window has to temporarily become current so the attributes
  106. #    can be changed.
  107. #
  108. function create_factory_window( x, y, xl, yl, flags ){        #PUBLIC #VOID
  109.     local win, fg, bg
  110.     local old = current_window
  111.     local oldlineformat = default_linenumber_format;
  112.  
  113.     if( argcount() < 5 )
  114.         flags = default_window_flags
  115.  
  116.  
  117.     default_linenumber_format = ""
  118.     win = create_window( x, y, xl, yl, flags )
  119.     default_linenumber_format = oldlineformat;
  120.  
  121.     if( win ){
  122.         current_window = win
  123.  
  124.         # initialize BAR_COLOR, HBAR_COLOR, and SHADOW_COLOR
  125.         init_menu_colors()
  126.  
  127.         # reset visible attributes, depending on display in use
  128.         color_text =        \
  129.             color_border    = BAR_COLOR
  130.         color_highlight        = HBAR_COLOR
  131.         color_linenumbers =    \
  132.             color_title    = TBAR_COLOR
  133.  
  134.         visible_newlines =            \
  135.             visible_virtual_lines =        \
  136.             visible_end_buffer =        \
  137.             visible_spaces =        \
  138.             visible_tabs =            \
  139.             visible_virtual_spaces = ""
  140.  
  141.         scroll_context_top =            \
  142.             scroll_context_left =        \
  143.             scroll_context_right =        \
  144.             scroll_context_bottom =        \
  145.             window_page_offset =        \
  146.             window_page_overlap = 0
  147.  
  148.         scroll_unit_horizontal =        \
  149.             scroll_unit_vertical =        \
  150.             scroll_means_pan = 1
  151.  
  152.         if ( window_valid( old ))
  153.             current_window = old
  154.     }
  155.  
  156.     return win
  157. }
  158.  
  159. ## factory_prompt()
  160. #
  161. #    Enhanced prompt function creates a factory window containing the
  162. #    dialog window.  This is used in cases where the prompt line is
  163. #    accompanied by a one-line instructional message.
  164. #
  165. #    Arguments:
  166. #        instructMsg  - contains the text of the instruction message
  167. #        historyTitle - the name of the history category
  168. #        prefix         - the text to display before the input area
  169. #        cmd         - the default value for prompt response
  170. #
  171. #    Return value:
  172. #        the response to prompt()
  173. #
  174. global function factory_prompt( instructMsg, historyTitle, prefix, cmd ) {    #PUBLIC #VOID
  175.     local    priorDialogWindow
  176.     local    instructionWindow
  177.     local    priorColorMessages = color_messages
  178.  
  179.     # create the outside window
  180.     instructionWindow = create_factory_window(    \
  181.             2, (display_height / 2) - 2,    \
  182.             76, 4,                \
  183.             WINDOW_BORDER )
  184.  
  185.     if ( !instructionWindow ) {
  186.         return 0
  187.     }
  188.  
  189.     # temporarily remove dialog window if one exists
  190.     if (( priorDialogWindow = dialog_window )) {
  191.         toggle_dialog( 0 )
  192.     }
  193.  
  194.     dialog_window = create_window(        \
  195.             3, display_height / 2,    \
  196.             74, 1,            \
  197.             WINDOW_SYSTEM )
  198.  
  199.     current_window = instructionWindow
  200.     window_cursor_x = 0
  201.     window_cursor_y = 0
  202.     write_window( instructMsg )
  203.  
  204.     color_messages = color_text
  205.  
  206.     # give a chance to edit the command
  207.     cmd = prompt_history( historyTitle, prefix, cmd )
  208.  
  209.     # restore dialog window
  210.     delete_window( instructionWindow )
  211.     delete_window( dialog_window )
  212.  
  213.     color_messages = priorColorMessages
  214.  
  215.     if (priorDialogWindow) {
  216.         toggle_dialog(1)
  217.     }
  218.  
  219.     return cmd
  220. }
  221.  
  222. ## create a 1/4 sized window in the middle of the screen:
  223. #
  224. function create_medium_window(){
  225.     local    w1
  226.     local    w2 = current_window
  227.  
  228.     w1 = create_window( display_width / 4,
  229.                 display_height / 4,
  230.                 display_width  / 2,
  231.                 display_height / 2 )
  232.     if ( w1 ) {
  233.         current_window = w1
  234.         color_current_window()        # maybe change its color
  235.         current_window = w2
  236.     }
  237.  
  238.     return w1
  239. }
  240.  
  241.  
  242. ## bleep and return 1 if current_window is a system window
  243. #    current_window by default
  244. function is_system_window(){                #PUBLIC #VOID
  245.     if( !current_window || and( window_flags, WINDOW_SYSTEM )){
  246.         beep()
  247.         return 1
  248.     }
  249.     return 0
  250. }
  251.  
  252. ## delete a window and it's attached buffer, if any
  253. #    this routine navigates around a common programming hazard when
  254. #    deleting temporary windows with attached buffers
  255. #    (the order of the deletes is very important)
  256. #
  257. function delete_window_and_buffer( win ){
  258.     local oldwin = current_window
  259.  
  260.     if( argcount())
  261.         assign_current_window( win )
  262.     else
  263.         win = current_window
  264.  
  265.     delete_buffer( current_buffer )
  266.     delete_window( current_window )
  267.  
  268.     if( oldwin != win )
  269.         assign_current_window( oldwin )
  270. }
  271.  
  272. ## delete_window function to be bound to function keys
  273. #    it protects the user from accidently having a system window
  274. #    such as the dialog window becoming current or being deleted.
  275. #
  276. #    delete_tiled_window offers similar protection
  277. #
  278. function delete_window_key(){                    #PUBLIC #VOID
  279.     if( is_system_window())
  280.         return
  281.     delete_window()
  282.     if( and( window_flags, WINDOW_SYSTEM ))
  283.         next_window()
  284. }
  285.  
  286. ## delete a "tiled" window; if any window is adjacent, expand the adjacent
  287. #    window to fill the space vacated by the window being deleted.
  288. #    If multiple windows are adjacent, only one is expanded.
  289. #    Adjacent windows are considered in the following order, and
  290. #    the first one encountered gets expanded: above, below, left & right.
  291. #
  292. #    This code works even when no windows exist.
  293.  
  294. function delete_tiled_window( w ){                #PUBLIC #INT
  295.     local flags, x0, y0, x1, y1
  296.     local ww, joined
  297.  
  298.     if( is_system_window())
  299.         return
  300.  
  301.     ww = current_window        # save entry value
  302.  
  303.     if( argcount() && window_valid( w ))
  304.         current_window = w    # temporary change to get coordinates
  305.     else
  306.         w = current_window    # current_window is the one to delete
  307.  
  308.     x0 = window_x0            # corner coordinates of ...
  309.     y0 = window_y0            # ... window to be deleted
  310.     x1 = x0 + window_width - 1
  311.     y1 = y0 + window_height - 1
  312.     flags = window_flags
  313.  
  314.     assign_current_window( ww )    # restore value on entry
  315.  
  316.     # if( and( flags, WINDOW_SYSTEM ))
  317.     #    error( "delete_tiled_window cannot delete system windows" )
  318.  
  319.     # look at all windows except w for adjacency to w
  320.  
  321.     do {
  322.         if( current_window != w )
  323.             joined = joinIfAdjacent( x0, y0, x1, y1 )
  324.             if( joined )
  325.                 break
  326.         next_window()
  327.     } while( ww != current_window )
  328.  
  329.     delete_window( w )
  330.     if( and( window_flags, WINDOW_SYSTEM ))
  331.         next_window()
  332.  
  333.     return joined
  334. }
  335.  
  336. # this function tests to see if current_window has an entire edge in common
  337. #    with the window specified by the arguments.  If so, current_window
  338. #    is expanded to fill the to-be vacated space.
  339. #
  340. #    A more general and arguably better algorithm would adjust windows
  341. #    that share only part of an adjacent edge, perhaps as a second pass.
  342. #
  343.  
  344. local function joinIfAdjacent( x0, y0, x1, y1 ){
  345.     local cx0 = window_x0
  346.     local cy0 = window_y0
  347.     local cx1 = cx0 + window_width - 1
  348.     local cy1 = cy0 + window_height - 1
  349.  
  350.  
  351.     if( is_system_window() || !and( window_flags, WINDOW_ZOOM))
  352.         return 0
  353.  
  354.     if( x0 == cx0 && x1 == cx1 ){
  355.         if( cy1 + 1 == y0  ){        # above
  356.             frame_window( x0, cy0, window_width, y1 - cy0 + 1 )
  357.             return 1
  358.         } else if( y1 + 1 == cy0 ){    # below
  359.             frame_window( x0, y0, window_width, cy1 - y0 + 1 )
  360.             return 1
  361.         }
  362.     } else if( y0 == cy0 && y1 == cy1 ){
  363.         if( cx1 + 1 == x0 ){        # left
  364.             frame_window( cx0, cy0, x1 - cx0 + 1, window_height )
  365.             return 1
  366.         } else if( x1 + 1 == cx0 ){    # right
  367.             frame_window( x0, y0, cx1 - x0 + 1, window_height )
  368.             return 1
  369.         }
  370.     }
  371.  
  372.     return 0
  373. }
  374.  
  375.  
  376. function create_tiled_window( pct, vert ){            #PUBLIC #VOID
  377.     if( vert ){
  378.         split_window_vertical( window_width * pct / 100 )
  379.     } else {
  380.         split_window_horizontal( window_height * pct / 100 )
  381.     }
  382. }
  383.  
  384.  
  385.  
  386. function split_window_horizontal( height ){            #PUBLIC #VOID
  387.     local x0 = window_x0
  388.     local y0 = window_y0
  389.     local xex = window_width
  390.     local yex0 = ( height > 0 ? height : window_height / 2 )
  391.     local yex1 = window_height - yex0
  392.     local y1 = y0 + yex0 # - 1
  393.     local w1
  394.  
  395.     if( is_system_window())
  396.         return FALSE
  397.  
  398.     if( yex0 < WINDOW_MIN_HEIGHT || yex1 < WINDOW_MIN_HEIGHT ){
  399.         warning( "window would be too small" )
  400.         return FALSE;
  401.     }
  402.  
  403.     # shrink current window and create a new one
  404.  
  405.     frame_window( x0, y0, xex, yex0 )
  406.     w1 = create_window( x0, y1, xex, yex1 )
  407.     if ( w1 ) {
  408.         current_window = w1
  409.         color_current_window()        # maybe change its color
  410.         attach_window_buffer( current_window, current_buffer )
  411.     } else {
  412.         warning( "unable to create window" )
  413.         return FALSE;
  414.     }
  415.  
  416.     return TRUE;
  417. }
  418.  
  419. function split_window_vertical( width ){            #PUBLIC #VOID
  420.     local x0 = window_x0
  421.     local y0 = window_y0
  422.     local yex = window_height
  423.     local xex0 = ( width > 0 ? width : window_width / 2 )
  424.     local xex1 = window_width - xex0
  425.     local x1 = x0 + xex0 # - 1
  426.     local w1
  427.  
  428.     if( is_system_window())
  429.         return FALSE
  430.  
  431.     if( xex0 < WINDOW_MIN_WIDTH || xex1 < WINDOW_MIN_WIDTH ){
  432.         warning( "window would be too small" )
  433.         return FALSE;
  434.     }
  435.  
  436.     # shrink existing and create a new one
  437.  
  438.     frame_window( x0, y0, xex0, yex )
  439.     w1 = create_window( x1, y0, xex1, yex )
  440.     if ( w1 ) {
  441.         current_window = w1
  442.         color_current_window()        # maybe change its color
  443.         attach_window_buffer( current_window, current_buffer )
  444.     } else {
  445.         warning( "unable to create window" )
  446.         return FALSE;
  447.     }
  448.  
  449.     return TRUE;
  450. }
  451.  
  452.  
  453. # toggle the presence of a standard 1-line bottom-of-the-screen dialog window,
  454. #    and adjust adjacent windows.  If a dialog window is present but not in
  455. #    the right place, it is toggled-off, but adjacent windows are not
  456. #    adjusted.
  457.  
  458. local prev_dialog_x0;
  459. local prev_dialog_y0;
  460. local prev_dialog_xExt;
  461. local prev_dialog_yExt;
  462.  
  463. function toggle_dialog( selection ){                #PUBLIC #VOID
  464.     local priorWindow = current_window
  465.     local w
  466.     local y1 = display_height - 1
  467.     local cw = current_window;
  468.     local def_col_text = default_color_text;
  469.  
  470.     if ( argcount() < 1 )
  471.         selection = !dialog_window
  472.     else
  473.         selection = 0+selection
  474.  
  475.     if ( selection && !dialog_window ) {
  476.  
  477.         ## create a permanent dialog window at the bottom of
  478.         ## the screen
  479.  
  480.  
  481.         default_color_text = color_messages;
  482.  
  483.         if (prev_dialog_xExt && prev_dialog_yExt)
  484.             dialog_window = create_window( prev_dialog_x0, prev_dialog_y0,    \
  485.                         prev_dialog_xExt, prev_dialog_yExt,        \
  486.                         WINDOW_SYSTEM )
  487.         else
  488.             dialog_window = create_window( 0, y1,            \
  489.                         display_width, 1,        \
  490.                         WINDOW_SYSTEM )
  491.  
  492.  
  493.         default_color_text = def_col_text;
  494.  
  495.         # allow all messages to be displayed
  496.         message_level = 0
  497.  
  498.         # adjust all non_system windows
  499.  
  500.         if ( !next_window() || and( window_flags, WINDOW_SYSTEM ) ) {
  501.             # only system windows are present
  502.             return
  503.         }
  504.  
  505.         w = current_window
  506.         do {
  507.             next_window()
  508.             if ( window_y0 + window_height - 1 == y1 ) {
  509.                 # shorten window by 1 line:
  510.                 frame_window(                \
  511.                     window_x0, window_y0,        \
  512.                     window_width, y1 - window_y0 )
  513.             }
  514.         } while( w != current_window )
  515.  
  516.     } else if( !selection && dialog_window ){
  517.  
  518.         ## delete any existing dialog window and substitute
  519.         ## a pop-up dialog window
  520.  
  521.         if ( priorWindow == dialog_window ) {
  522.             priorWindow = 0
  523.         }
  524.  
  525.         current_window = dialog_window;
  526.         prev_dialog_x0 = window_x0;
  527.         prev_dialog_y0 = window_y0;
  528.         prev_dialog_xExt = window_width;
  529.         prev_dialog_yExt = window_height;
  530.         assign_current_window( cw );
  531.  
  532.         delete_window( dialog_window )
  533.  
  534.         # allow only notify(), warning(), error() but not message()
  535.         # to pop-up in dialog window
  536.         message_level = 1
  537.  
  538.         # adjust all non_system windows
  539.  
  540.         if ( !next_window() || and( window_flags, WINDOW_SYSTEM ) ) {
  541.             # only system windows are present
  542.             return
  543.         }
  544.  
  545.         w = current_window
  546.         do {
  547.             next_window()
  548.             if ( window_y0 + window_height == y1 ) {
  549.                 if ( and( window_flags, WINDOW_ZOOM )){
  550.                     # lengthen window by 1 line:
  551.                     frame_window(                \
  552.                         window_x0, window_y0,        \
  553.                         window_width, y1 - window_y0 + 1 )
  554.                 }
  555.             }
  556.         } while( w != current_window )
  557.     }
  558.  
  559.     if ( priorWindow ) {
  560.         current_window = priorWindow
  561.     }
  562. }
  563.  
  564.  
  565. global    time_window = 0            # time_window id
  566. global    clock_on = FALSE        # current clock setting
  567. local    TIME_LENGTH = 16        # amount of ctime() you want to see
  568. #local    CTIME_LENGTH = 19        # length of ctime() return string
  569. local    clock_id = 0            # function id of display_time()
  570. local    ctime_start = 1            # first char index in ctime() string
  571.  
  572. global function toggle_clock( on ){                #PUBLIC #VOID
  573.     local    old_clock = clock_on
  574.  
  575.     clock_on = (argcount() < 1 ) ? !clock_on : 0+on
  576.  
  577.     if ( clock_on != old_clock ) {
  578.         if (clock_on) {
  579.             time_window = create_window( \
  580.                     display_width-TIME_LENGTH, \
  581.                     display_height-1, \
  582.                     TIME_LENGTH, 1, \
  583.                     WINDOW_SYSTEM )
  584.  
  585.             attach_event_handler( EVENT_IDLE_TIME, \
  586.                 clock_id = function_id( "display_time" ))
  587.             prev_idle_time = idle_time - 1;
  588.             seconds = 60;
  589.             displayit = 1;
  590.         } else {
  591.             delete_event( EVENT_IDLE_TIME, clock_id )
  592.             delete_window( time_window )
  593.             time_window = 0
  594.         }
  595.     }
  596.     return clock_on
  597. }
  598.  
  599. local    displayit = 0;
  600. local    prev_idle_time = 0;
  601. local    seconds = 0;
  602.  
  603. function display_time() {
  604.     if ((idle_time != prev_idle_time) || displayit) {
  605.         prev_idle_time = idle_time;
  606.         if ((seconds++ > 20) || displayit) {
  607.             displayit = 0;
  608.             seconds = 0;
  609.             write_window(    \
  610.                 substr( ctime(), ctime_start, TIME_LENGTH ), time_window )
  611.             display_update()
  612.         }
  613.     }
  614. }
  615.  
  616. global function shrink_windows_down_1(){
  617.     local    priorWindow = current_window
  618.     local    w
  619.  
  620.     if ( !next_window() || and( window_flags, WINDOW_SYSTEM ) ) {
  621.         # only system windows are present
  622.         return
  623.     }
  624.  
  625.     w = current_window
  626.     do {
  627.         next_window()
  628.         if( window_y0 == 0 ){
  629.             # shorten window by 1 line:
  630.             frame_window(                \
  631.                 window_x0, window_y0+1,        \
  632.                 window_width, window_height - 1 )
  633.         }
  634.     } while( w != current_window )
  635.  
  636.     if ( priorWindow ) {
  637.         current_window = priorWindow
  638.     }
  639. }
  640.  
  641. global function grow_windows_up_1(){
  642.     local    priorWindow = current_window
  643.     local    w
  644.  
  645.     if ( !next_window() || and( window_flags, WINDOW_SYSTEM ) ) {
  646.         # only system windows are present
  647.         return
  648.     }
  649.  
  650.     w = current_window
  651.     do {
  652.         next_window()
  653.         if( window_y0 == 1 ){
  654.             # shorten them by 1 line:
  655.             frame_window(                \
  656.                 window_x0, 0,            \
  657.                 window_width, window_height + 1 )
  658.         }
  659.     } while( w != current_window )
  660.  
  661.     if ( priorWindow ) {
  662.         current_window = priorWindow
  663.     }
  664. }
  665.  
  666.  
  667.  
  668. local dialog_nesting = 0
  669. local dialog_was_off = 0
  670. local dialog_prev_cur
  671.  
  672. # make sure there is a dialog window for a series of interactions.
  673.  
  674. function begin_dialog(){
  675.     if( dialog_nesting++ == 0    \
  676.     && ( dialog_was_off = !dialog_window )){
  677.         dialog_prev_cur = current_window
  678.         popup_dialog()
  679.     }
  680. }
  681.  
  682. # remove the dialog window, if any, that was created by begin_dialog()
  683. function end_dialog(){
  684.     if( dialog_nesting > 0        \
  685.     && --dialog_nesting == 0    \
  686.     && dialog_was_off ){
  687.         assign_current_window( dialog_prev_cur )
  688.         delete_window( dialog_window )
  689.     }
  690. }
  691.  
  692. # Create a dialog window in the same location and of the same
  693. # size as a pop-up dialog box would be.
  694. local function popup_dialog(){
  695.     local    screenThird = display_height / 3
  696.     local    cursor_y
  697.  
  698.     # attempt to avoid the current cursor position
  699.     cursor_y = window_y0 + window_text_y0 + (current_line - window_first)
  700.     if (cursor_y < screenThird) {
  701.         cursor_y = screenThird * 2
  702.     } else if (cursor_y > screenThird * 2) {
  703.         cursor_y = screenThird
  704.     } else {
  705.         cursor_y = display_height * 2 / 3 + 2
  706.     }
  707.  
  708.     dialog_window = create_window(        \
  709.             2, cursor_y,    \
  710.             display_width - 4, 3,    \
  711.             WINDOW_MENU0 )
  712. }
  713.  
  714. # toggle line numbers in the current window
  715.  
  716. global nominal_linenumber_format = "%5d "
  717.  
  718. function toggle_linenumbers( selection ){
  719.  
  720.     if( is_system_window())
  721.         return FALSE
  722.  
  723.     if( argcount() < 1 )
  724.         selection = !linenumber_format
  725.  
  726.     if( 0+selection )
  727.         linenumber_format = nominal_linenumber_format
  728.     else
  729.         linenumber_format = ""
  730. }
  731.  
  732. ## toggle presence/absence of borders
  733. #
  734. #    Toggle_borders accepts an optional argument:
  735. #        true => set borders to their nominal value
  736. #        false => remove borders and titles.
  737. #    If the argument is omitted, the borders are "toggled".
  738. #
  739. #    Since there are several border styles we cannot simply toggle bits.
  740. #    Instead, we save the border setting when it is turned off, and
  741. #    restore the previously saved setting when toggeling it on.
  742. #
  743. #    When there are multiple border styles, and current_window is changed
  744. #    between calls to toggle_border, the effect may be to transfer border
  745. #    styles from window to window.
  746. #
  747. #    If borders are to be turned-off by default, then nominal_border_flags
  748. #    should be set in addition to default_window_flags.
  749.  
  750. global nominal_border_flags = WINDOW_STANDARD
  751.  
  752. function toggle_borders( selection ){                #PUBLIC #VOID
  753.     local border_flags = WINDOW_BORDERS + WINDOW_HEADERS
  754.     local noborders = and( window_flags, not( border_flags ))
  755.     local   borders = and( window_flags,      border_flags )
  756.  
  757.     if( is_system_window())
  758.         return FALSE
  759.  
  760.     if( argcount() < 1 )
  761.         selection = !borders        # toggle if no arg
  762.  
  763.     if( 0+selection ){            # restore nominal borders
  764.         window_flags = nominal_border_flags
  765.  
  766.     } else {                # remove nominal borders
  767.         nominal_border_flags = window_flags
  768.         window_flags = noborders
  769.     }
  770. }
  771.  
  772. ### window resizing, positioning & scrolling
  773.  
  774.  
  775. function larger_window(){
  776.     local wz = and( window_flags, WINDOW_ZOOM )
  777.  
  778.     if( is_system_window())
  779.         return FALSE
  780.  
  781.     if( wz == WINDOW_COLLAPSED )
  782.         restore_window()
  783.     else if( wz == WINDOW_NORMAL )
  784.         expand_window()
  785. }
  786.  
  787. function smaller_window(){
  788.     local wz = and( window_flags, WINDOW_ZOOM )
  789.  
  790.     if( is_system_window())
  791.         return FALSE
  792.  
  793.     if( wz == WINDOW_EXPANDED )
  794.         restore_window()
  795.     else if( wz == WINDOW_NORMAL )
  796.         collapse_window()
  797. }
  798.  
  799. function scroll_down_1(){
  800.     scroll_vertical( 1, scroll_or_pan())
  801. }
  802.  
  803. function scroll_up_1(){
  804.     scroll_vertical( -1, scroll_or_pan())
  805. }
  806.  
  807. function scroll_down_half(){
  808.     local h = window_height / 2
  809.     scroll_vertical(( h <= 0 ? 1 : h ), scroll_or_pan())
  810. }
  811.  
  812. function scroll_up_half(){
  813.     local h = window_height / 2
  814.     scroll_vertical( -( h <= 0 ? 1 : h ), scroll_or_pan())
  815. }
  816.  
  817. function scroll_left_1(){
  818.     scroll_horizontal( -1, scroll_or_pan())
  819. }
  820.  
  821. function scroll_right_1(){
  822.     scroll_horizontal( 1, scroll_or_pan())
  823. }
  824.  
  825. # these functions reposition the window so that the current line is
  826. #    in the indicated position (if possible):
  827.  
  828. global function scroll_window_top( n ){                #PUBLIC #VOID
  829.     if( n >= window_text_height )
  830.         n = window_text_height - 1
  831.     scroll_vertical( distance_to_window_top() - n, scroll_or_pan())
  832. }
  833.  
  834. global function scroll_window_bottom( n ){            #PUBLIC #VOID
  835.     if( n >= window_text_height )
  836.         n = window_text_height - 1
  837.     scroll_vertical( - distance_to_window_bottom() + n, scroll_or_pan())
  838. }
  839.  
  840. global function scroll_window_middle( n ){            #PUBLIC #VOID
  841.  
  842.     # arguably should guard against too large values of abs(n)
  843.  
  844.     scroll_vertical( -distance_to_window_middle() - n, scroll_or_pan())
  845. }
  846.  
  847. ## center_cursor
  848. #    similar to scroll_window_middle but never changes the position in
  849. #    the buffer (i.e. current_line or current_column).  This function is
  850. #    useful for restoring a convenient window orientation when the cursor
  851. #    has drifted too far to the top or bottom.
  852. #
  853. global function center_cursor(){                #PUBLIC #VOID
  854.     local    save_context_top = scroll_context_top
  855.     scroll_context_top = 0
  856.  
  857.     # (following removed because it was too slow)
  858.     ## use row if specified, otherwise center the cursor vertically
  859.     #if ( argcount() ) {
  860.     #    if ( row >= window_text_height ) {
  861.     #        row = window_text_height - 1
  862.     #    }
  863.     #} else {
  864.     #    row = shiftr( window_text_height, 1 )
  865.     #}
  866.  
  867.     scroll_vertical( current_line - window_first - shiftr( window_text_height, 1 ), 0 )
  868.  
  869.     scroll_context_top = save_context_top
  870. }
  871.  
  872.  
  873. ## scroll_or_pan -- determine to scroll or pan by
  874. #    interrogating the scroll_means_pan status and
  875. #    complementing it if the SCROLL_LOCK key is pressed
  876. #
  877. global function scroll_or_pan(){
  878.     local smp = !scroll_means_pan    # !! smp default should be reversed
  879.     return xor_scroll_lock( smp )
  880. }
  881.  
  882. ## interrogate status of scroll-lock key
  883.  
  884. function scroll_lock_status(){
  885.     return !!and( keyboard_flags, KB_SCROLL_LOCK )
  886. }
  887.  
  888. ## xor the argument with scroll_lock_status()
  889.  
  890. function xor_scroll_lock( var ){
  891.     return xor( var, scroll_lock_status())
  892. }
  893.  
  894. ### distances from the cursor to current_window's borders
  895. #    these are relative to a position within the window to the given edge.
  896. #    if the cursor happens to be outside window-borders the values may
  897. #    be negative.
  898.  
  899. function distance_to_window_top(){                #PUBLIC #INT
  900.     return    current_line - window_first
  901. }
  902.  
  903. function distance_to_window_bottom(){                #PUBLIC #INT
  904.     return    window_first + window_text_height - current_line - 1
  905. }
  906.  
  907. function distance_to_window_left(){                #PUBLIC #INT
  908.     return    current_column - window_margin - 1
  909. }
  910.  
  911. function distance_to_window_right(){                #PUBLIC #INT
  912.     return    window_margin + window_text_width - current_column
  913. }
  914.  
  915. # This function lacks symmetry with the four above.  We eventually may need
  916. # to distinguish between horizontal, vertical and combined centering.  For
  917. # now we only need vertical motion, and this computes the quantity, m,
  918. # such that    current_line += m
  919. # and        scroll_vertical( m )
  920. # both put the current line into the middle of the screen.
  921. #
  922. function distance_to_window_middle(){
  923.     # message( "wf: %d, wth: %d, line=%d",        \
  924.     #     window_first,                \
  925.     #     window_text_height,            \
  926.     #     current_line )
  927.     
  928.     return window_first + window_text_height / 2 - current_line
  929. }
  930.  
  931. ### window/buffer organization
  932.  
  933. ## collapse all windows but the current to an orderly array of icons
  934.  
  935. function organize_windows(){                #PUBLIC #VOID
  936.     local x = 2
  937.     local y = 1
  938.     local dx = 16
  939.     local dy = 2
  940.     local w = current_window
  941.  
  942.     do {
  943.         if( !and( window_flags, WINDOW_SYSTEM )){
  944.             collapse_window()
  945.             move_window( x, y )
  946.             y += dy
  947.             if( y >= display_height - 1 ){
  948.                 y = 1
  949.                 x += dx
  950.             }
  951.         }
  952.         next_window( "", 1 )
  953.     } while( w != current_window )    # restores current_window
  954. }
  955.  
  956. ## create an icon for each buffer not already contained in a window
  957. #    and then organize the resulting windows.  The windows and
  958. #    icons are initially created all on top of each other.
  959. #
  960. function organize_buffers(){                #PUBLIC #VOID
  961.     local w
  962.     local b
  963.     local use
  964.  
  965.     if ( !(w = current_window))
  966.         return
  967.  
  968.     do {
  969.         if ( !and( window_flags, WINDOW_SYSTEM ) ) {
  970.             use[ window_name ]++
  971.         }
  972.         next_window( "", 1 )
  973.     } while( w != current_window )
  974.  
  975.     b = current_buffer
  976.     do {
  977.         if ( !and( buffer_flags, BUFFER_SYSTEM )  &&
  978.                 !( buffer_name in use )) {
  979.             attach_window_buffer(            \
  980.                 create_medium_window(),        \
  981.                 current_buffer )
  982.             collapse_window()
  983.         }
  984.         next_buffer( "", 1 )
  985.     } while( b != current_buffer )
  986.  
  987.     organize_windows()
  988.  
  989.     assign_current_window( w )
  990.     current_buffer = b
  991. }
  992.  
  993.  
  994. ### fine-grain window positioning & resizing -- mouse alternates
  995. #
  996. #    These functions support moving and resizing windows via the keypad.
  997. #
  998.  
  999. ##
  1000.  
  1001. local adjust_position        # true if moving, false if resizing
  1002. local adjust_keymap        # keymap to use to adjust windows
  1003.  
  1004.  
  1005. ## resize or move a window (opposite if scroll lock is on)
  1006. #
  1007. #    xor(  pos, scroll_lock_status()) => moving
  1008. #    xor( !pos, scroll_lock_status()) => resizing (default if called from keymap)
  1009.  
  1010. function adjust_window( pos ){                #PUBLIC #VOID
  1011.     local    prev_keymap = current_keymap
  1012.     local    x0 = window_x0        # save current window pos/size
  1013.     local    y0 = window_y0
  1014.     local    w = window_width
  1015.     local    h = window_height
  1016.     local    tempDialog
  1017.  
  1018.     if ( is_system_window()) {
  1019.         return FALSE
  1020.     }
  1021.  
  1022.     adjust_position = !!pos
  1023.  
  1024.     if( !adjust_keymap ){
  1025.         current_keymap = adjust_keymap = create_keymap( empty_keymap )
  1026.         assign_key( "<Up>",    "adjust_window_key  0 -1" )
  1027.         assign_key( "<Down>",    "adjust_window_key  0  1" )
  1028.         assign_key( "<Right>",    "adjust_window_key  1  0" )
  1029.         assign_key( "<Left>",    "adjust_window_key -1  0" )
  1030.         assign_key( "<Enter>",    "process_end 0" )
  1031.         assign_key( "<Esc>",    "process_end 1" )
  1032.     } else {
  1033.         current_keymap = adjust_keymap
  1034.     }
  1035.  
  1036.     # create a temporary dialog window at the bottom of the screen
  1037.     if ( !dialog_window ) {
  1038.         dialog_window = tempDialog = create_window(    \
  1039.                     0, display_height - 1,    \
  1040.                     display_width, 1,    \
  1041.                     WINDOW_SYSTEM )
  1042.     }
  1043.     notify( "Use arrow keys to adjust window, ENTER to accept, and ESC to cancel." )
  1044.     raise_window( dialog_window )
  1045.  
  1046.     # process the keymap defined above
  1047.     if( 0+process_begin() ) {        # canceled...
  1048.         message( "Window adjustment canceled." )
  1049.         frame_window( x0, y0, w, h )    # restore window pos/size
  1050.     } else {                # accepted...
  1051.         message( "" )
  1052.     }
  1053.  
  1054.     # remove the temporary dialog window if we created one
  1055.     if ( tempDialog ) {
  1056.         delete_window( dialog_window )
  1057.     }
  1058.  
  1059.     # restore the original keymap
  1060.     current_keymap = prev_keymap
  1061. }
  1062.  
  1063. function adjust_window_key( x, y ){
  1064.     if( xor_scroll_lock( adjust_position ))    # move
  1065.         frame_window( window_x0 + x,            \
  1066.             window_y0 + y,                \
  1067.             window_width,                \
  1068.             window_height )
  1069.     else                    # resize
  1070.         frame_window( window_x0,            \
  1071.             window_y0,                \
  1072.             window_width + x,            \
  1073.             window_height + y )
  1074. }
  1075.  
  1076.  
  1077.  
  1078. ## show_visibles()
  1079. #
  1080. #    This function displays all tabs, spaces, newline chars, etc. which
  1081. #    are accessible via visible_xxx variables.
  1082.  
  1083. global function show_visibles() {                #PUBLIC #VOID
  1084.     visible_virtual_lines = "~"
  1085.     visible_end_buffer = ""
  1086.     visible_newlines = "■"
  1087.     visible_spaces = "·"
  1088.     visible_tabs = ""
  1089.     visible_virtual_spaces = " "
  1090. }
  1091.  
  1092. ## reset_visibles()
  1093. #
  1094. #    This function resets all of the "visible" representations for
  1095. #    otherwise non-printing attributes to their less visible defaults.
  1096.  
  1097. function reset_visibles() {                    #PUBLIC #VOID
  1098.     visible_virtual_lines = ""
  1099.     visible_end_buffer = ""
  1100.     visible_newlines = ""
  1101.     visible_spaces = " "
  1102.     visible_tabs = " "
  1103.     visible_virtual_spaces = " "
  1104.     default_visible_virtual_lines = ""
  1105.     default_visible_end_buffer = ""
  1106.     default_visible_newlines = ""
  1107.     default_visible_spaces = " "
  1108.     default_visible_tabs = " "
  1109.     default_visible_virtual_spaces = " "
  1110. }
  1111.  
  1112.  
  1113. ## valid_window()
  1114. #
  1115. #  given a window id, return TRUE if it is a valid window, otherwise FALSE
  1116. #
  1117. function valid_window( winid ){
  1118.     return (winid && read_window( 1, winid )) ? TRUE : FALSE;
  1119. }
  1120.  
  1121. ## assign_current_window()
  1122. #
  1123. #  assign a window id to the current window iff the window id is valid
  1124. #
  1125. function assign_current_window( winid ){
  1126.     if (window_valid( winid ))
  1127.         current_window = winid;
  1128. }
  1129.  
  1130. ## toggle_window_zoom()
  1131. #
  1132. # toggles the WINDOW_EXPANDED bit in the window_flags.  This
  1133. # has the effect of alternately expanding and restoring the size
  1134. # of the current window.
  1135. #
  1136. global function toggle_window_zoom() {
  1137.     local x = 0;
  1138.     local y = 0;
  1139.     local xExt = display_width;
  1140.     local yExt = display_height;
  1141.     local cw = current_window;
  1142.  
  1143.     if ( and(window_flags,WINDOW_EXPANDED) )
  1144.         restore_window()
  1145.     else {
  1146.         expand_window()
  1147.  
  1148.         if (help_resident) {
  1149.             x = 0;
  1150.             y = 1;
  1151.             yExt--;
  1152.         }
  1153.         if (dialog_window) {
  1154.             current_window = dialog_window;
  1155.             if (window_y0 == display_height-1)
  1156.                 yExt--;
  1157.             assign_current_window( cw );
  1158.         }
  1159.         frame_window( x, y, xExt, yExt );
  1160.     }
  1161. }
  1162.  
  1163. global function next_window_key(){                #PUBLIC #VOID
  1164.     local     cw = current_window;
  1165.     while( (next_window() != cw) &&
  1166.         (and( window_flags,WINDOW_ZOOM) == WINDOW_HIDDEN))
  1167.         continue;
  1168. }
  1169.  
  1170. global function prev_window_key(){                #PUBLIC #VOID
  1171.     local     cw = current_window;
  1172.     while( (prev_window() != cw) &&
  1173.         (and( window_flags,WINDOW_ZOOM) == WINDOW_HIDDEN))
  1174.         continue;
  1175. }
  1176.  
  1177.