home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / desktop / t / utils / !Logger_C_ROTEXT < prev    next >
Encoding:
Text File  |  1993-05-31  |  27.5 KB  |  1,044 lines

  1. /*
  2.  *
  3.  *      Title     : Text display routines.
  4.  *      System    : Any */
  5. #define Version     "2.1"
  6. /*      Copyright : (c) John H. Winters
  7.  *      Date      : 7th October, 1992
  8.  *      Author    : John H. Winters
  9.  *
  10.  *      Function  : Displays text in a window under Risc-OS.
  11.  *
  12.  *
  13.  *      Modification history.
  14.  *
  15.  *      Version   : 1.1
  16.  *      Date      : 17th October, 1992
  17.  *      Author    : John H. Winters
  18.  *      Changes   : Implemented a more efficient way of scrolling the window.
  19.  *
  20.  *      Version   : 1.2
  21.  *      Date      : 24th October, 1992
  22.  *      Author    : John H. Winters
  23.  *      Changes   : Added some defence against recursive calls.
  24.  *
  25.  *      Version   : 1.3
  26.  *      Date      : 12th November, 1992
  27.  *      Author    : John H. Winters
  28.  *      Changes   : Added a visible cursor.
  29.  *
  30.  *      Version   : 2.0
  31.  *      Date      : 23rd May, 1993
  32.  *      Author    : John H. Winters
  33.  *      Changes   : Ported to Risc OS 3.1
  34.  *
  35.  *      Version   : 2.1
  36.  *      Date      : 31st May, 1993
  37.  *      Author    : John H. Winters
  38.  *      Changes   : New parameter to WIMP_ReportError
  39.  *
  40.  *      Version   : 
  41.  *      Date      : 
  42.  *      Author    : 
  43.  *      Changes   : 
  44.  *
  45.  */
  46.  
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include <stdlib.h>
  50.  
  51. #include "global.h"
  52. #if !defined (ARTHUR)
  53. #error This module is for Risc-OS only.
  54. #endif
  55. #include "vdu.h"
  56. #include "wimplib.h"
  57. #include "winapp.h"
  58. #include "logging.h"
  59. #include "linklist.h"
  60. #include "text.h"
  61.  
  62. /*
  63.  *============================================================================
  64.  *
  65.  *  Hash defines.
  66.  *
  67.  *============================================================================
  68.  */
  69.  
  70. #define CHAR_HEIGHT    32
  71. #define CHAR_WIDTH     16
  72. #define CLG            16
  73. #define FLASH_INTERVAL 50
  74. #define LR_BORDER      4
  75. #define TB_BORDER      4
  76. #define TEMPLATE_FILE  "Templates"
  77. #define TEMPLATE_NAME  "TEXTWIN"
  78. #define Y_OFFSET       1
  79.  
  80. /*
  81.  *============================================================================
  82.  *
  83.  *  Type definitions.
  84.  *
  85.  *============================================================================
  86.  */
  87.  
  88. typedef struct t_TXTI_Record {
  89.     t_LL_Header      header ;
  90.     t_window_block  *window_block ;
  91.     t_window_handle  window_handle ;
  92.     uint             visible ;
  93.     uint             cursor_on ;
  94.     uint             cursor_visible ;
  95.     uint             ticker_active ;
  96.     uint             height ;
  97.     uint             width ;
  98.     /*
  99.      *  The next two are just to speed calculations.
  100.      */
  101.     uint             osheight ;
  102.     uint             oswidth ;
  103.     uint             row ;
  104.     uint             col ;
  105.     uint             been_open ;
  106. } t_TXTI_Record ;
  107.  
  108. /*
  109.  *  A little note on the visible, cursor_on and cursor_visible items in the
  110.  *  above data structure.  This module implements a flashing cursor, which
  111.  *  the client code can activiate and deactivate.  This leads to some
  112.  *  interesting messing about.
  113.  *
  114.  *  visible is set to TRUE iff the window is currently open on the screen.
  115.  *  This doesn't necessarily mean that the window is actually visible to the
  116.  *  user, because it could be overlaid by another window.  It does however
  117.  *  mean that we can sensibly make calls on routines to draw in the window.
  118.  *
  119.  *  cursor_on is set to TRUE iff the client code has activated the visible
  120.  *  cursor.
  121.  *
  122.  *  cursor_visible is meaningful iff both the preceding items are TRUE.
  123.  *  In that case, it indicates whether the flashing cursor is currently in
  124.  *  a "mark" state.  If either of the other two is FALSE, then the cursor
  125.  *  is by implication invisible.  Whenever we move to a state where both
  126.  *  the others are TRUE, cursor_visible is set to FALSE.
  127.  *
  128.  */
  129.  
  130. /*
  131.  *============================================================================
  132.  *
  133.  *  Local data.
  134.  *
  135.  *============================================================================
  136.  */
  137.  
  138. static uint        InEventHandler = FALSE ;
  139. static t_LL_Header RecordAnchor   = LL_EMPTY ;
  140. static uint        TemplateLoaded = FALSE ;
  141.  
  142. /*
  143.  *============================================================================
  144.  *
  145.  *  Forward declarations.
  146.  *
  147.  *============================================================================
  148.  */
  149.  
  150. static void ActivateCursor (
  151.     t_TXT_Handle handle) ;
  152.  
  153. static void DeactivateCursor (
  154.     t_TXT_Handle handle) ;
  155.  
  156. static uint EventHandler (
  157.     t_poll_block *poll_block,
  158.     void         *reference) ;
  159.  
  160. static uint HandleValid (
  161.     t_TXT_Handle handle) ;
  162.  
  163. static void PlotCursor (
  164.     t_TXT_Handle handle) ;
  165.  
  166. static void RedrawWindow (
  167.     t_TXT_Handle    handle,
  168.     t_redraw_block *r) ;
  169.  
  170. static void TickerHandler (
  171.     void *reference) ;
  172.  
  173. /*
  174.  *============================================================================
  175.  *
  176.  *  Externally visible routines.
  177.  *
  178.  *============================================================================
  179.  */
  180.  
  181. void TXT_CursorOff (
  182.     t_TXT_Handle handle)
  183.  
  184. /*
  185.  *  Function :
  186.  *                  Turn the flashing cursor off.
  187.  *
  188.  *  Parameters :
  189.  *                  handle  Handle on the relevant window.
  190.  *
  191.  *  Returns :
  192.  *                  None.
  193.  *
  194.  */
  195.  
  196. {
  197.     if (HandleValid (handle))
  198.     {
  199.         if (handle->cursor_on)
  200.         {
  201.             handle->cursor_on = FALSE ;
  202.             if (handle->visible)
  203.             {
  204.                 DeactivateCursor (handle) ;
  205.             }
  206.         }
  207.     }
  208.     else
  209.     {
  210.         LOG_Warning ("TXT: Invalid handle passed to TXT_CursorOff.\n") ;
  211.     }
  212. }
  213.  
  214.   
  215. void TXT_CursorOn (
  216.     t_TXT_Handle handle)
  217.  
  218. /*
  219.  *  Function :
  220.  *                  Turn the cursor on in a text window.
  221.  *
  222.  *  Parameters :
  223.  *                  handle  The handle of the window to turn it on in.
  224.  *
  225.  *  Returns :
  226.  *                  None.
  227.  *
  228.  */
  229.  
  230. {
  231.     if (HandleValid (handle))
  232.     {
  233.         if (!handle->cursor_on)
  234.         {
  235.             handle->cursor_on = TRUE ;
  236.             if (handle->visible)
  237.             {
  238.                 ActivateCursor (handle) ;
  239.             }
  240.         }
  241.     }
  242.     else
  243.     {
  244.         LOG_Warning ("TXT: Invalid handle passed to TXT_CursorOn.\n") ;
  245.     }
  246. }
  247.  
  248.   
  249. t_TXT_Handle TXT_CreateWindow (
  250.     uint height,
  251.     uint width)
  252.  
  253. /*
  254.  *  Function :
  255.  *                  Create a text window (conceptually) for later use.
  256.  *
  257.  *  Parameters :
  258.  *                  height      Height of the window in characters.
  259.  *                  width       Width of the window in characters.
  260.  *
  261.  *  Returns :
  262.  *                  Handle on the new structure, or NULL if not succesful.
  263.  *
  264.  */
  265.  
  266. {
  267.     u8            *body ;
  268.     t_TXTI_Record *current ;
  269.     t_box          extent ;
  270.  
  271.     if (TemplateLoaded)
  272.     {
  273.         current = malloc (sizeof (t_TXTI_Record) + (height * width)) ;
  274.         if (current == NULL)
  275.         {
  276.             LOG_Error ("TXT: Can't allocate memory for a text window.\n") ;
  277.         }
  278.         else
  279.         {
  280.             if (WA_CreateWindow (TEMPLATE_NAME,
  281.                                  &(current->window_block),
  282.                                  &(current->window_handle)))
  283.             {
  284.                 if (WA_ClaimEvent (DONT_CARE,
  285.                                    current->window_handle,
  286.                                    DONT_CARE,
  287.                                    EventHandler,
  288.                                    current))
  289.                 {
  290.                     LL_InitHeader (&(current->header)) ;
  291.                     current->visible        = FALSE ;
  292.                     current->cursor_on      = FALSE ;
  293.                     current->cursor_visible = FALSE ;
  294.                     current->ticker_active  = FALSE ;
  295.                     current->height         = height ;
  296.                     current->width          = width ;
  297.                     current->osheight       = height * CHAR_HEIGHT ;
  298.                     current->oswidth        = width * CHAR_WIDTH ;
  299.                     current->row            = 0 ;
  300.                     current->col            = 0 ;
  301.                     current->been_open      = FALSE ;
  302.                     LL_AddToHead (&RecordAnchor,
  303.                                   &(current->header)) ;
  304.                     body = (u8 *) (current + 1) ;
  305.                     memset (body, ' ', width * height) ;
  306.                     /*
  307.                      *  Calculate the required extent.  The two multipliers
  308.                      *  are specified by Acorn and are constant (PRM P.1149)
  309.                      */
  310.                     extent.min.x = 0 - LR_BORDER ;
  311.                     extent.min.y = -(current->osheight) - TB_BORDER ;
  312.                     extent.max.x = current->oswidth + LR_BORDER ;
  313.                     extent.max.y = 0 + TB_BORDER ;
  314.                     LOG_OSError (WIMP_SetExtent (current->window_handle,
  315.                                                  &extent)) ;
  316.                     return (current) ;
  317.                 }
  318.                 else
  319.                 {
  320.                     LOG_Error ("TXT: Failed to claim window events.\n") ;
  321.                 }
  322.                 WA_DeleteWindow (current->window_handle) ;
  323.             }
  324.             else
  325.             {
  326.                 LOG_Error ("TXT: Failed to create window.\n") ;
  327.             }
  328.             free (current) ;
  329.         }
  330.     }
  331.     else
  332.     {
  333.         LOG_Error ("TXT: Can't create a window because the template is not loaded.\n") ;
  334.         LOG_Error ("TXT: Use TXT_LoadResources during initialisation.\n") ;
  335.     }
  336.     return (NULL) ;
  337. }
  338.  
  339.  
  340. uint TXT_DisplayWindow (
  341.     t_TXT_Handle handle)
  342.  
  343. /*
  344.  *  Function :
  345.  *                  Make our window actually appear on the screen.
  346.  *
  347.  *  Parameters :
  348.  *                  handle      Handle on the window to display.
  349.  *
  350.  *  Returns :
  351.  *                  TRUE if we succeed, FALSE otherwise.
  352.  *
  353.  */
  354.  
  355. {
  356.     uint          result ;
  357.     t_state_block state ;
  358.  
  359.     result = FALSE ;
  360.     if (InEventHandler)
  361.     {
  362.         result = TRUE ;
  363.     }
  364.     else
  365.     {
  366.         if (HandleValid (handle))
  367.         {
  368.             if (handle->visible)
  369.             {
  370.                 result = TRUE ;
  371.             }
  372.             else
  373.             {
  374.                 if (LOG_OSError (WIMP_GetWindowState (handle->window_handle,
  375.                                                       &state)) == NULL)
  376.                 {
  377.                     if (!handle->been_open)
  378.                     {
  379.                         state.open_block.scroll_offset.y = TB_BORDER ;
  380.                         state.open_block.scroll_offset.x = -LR_BORDER ;
  381.                     }
  382.                     if (LOG_OSError (WIMP_OpenWindow (&state.open_block)) == NULL)
  383.                     {
  384.                         handle->visible   = TRUE ;
  385.                         handle->been_open = TRUE ;
  386.                         if (handle->cursor_on)
  387.                         {
  388.                             ActivateCursor (handle) ;
  389.                         }
  390.                         result = TRUE ;
  391.                     }
  392.                 }
  393.             }
  394.         }
  395.         else
  396.         {
  397.             LOG_Warning ("TXT: Invalid handle passed to TXT_DisplayWindow.\n") ;
  398.         }
  399.     }
  400.     return (result) ;
  401. }
  402.  
  403.  
  404. void TXT_HideWindow (
  405.     t_TXT_Handle handle)
  406.  
  407. /*
  408.  *  Function :
  409.  *                  Remove our window from the screen.
  410.  *
  411.  *  Parameters :
  412.  *                  handle      Handle on the window to remove.
  413.  *
  414.  *  Returns :
  415.  *                  None.
  416.  *
  417.  */
  418.  
  419. {
  420.     if (HandleValid (handle))
  421.     {
  422.         if (handle->visible)
  423.         {
  424.             LOG_OSError (WIMP_CloseWindow (handle->window_handle)) ;
  425.             handle->visible = FALSE ;
  426.             if (handle->cursor_on)
  427.             {
  428.                 DeactivateCursor (handle) ;
  429.             }
  430.         }
  431.     }
  432.     else
  433.     {
  434.         LOG_Warning ("TXT: Invalid handle passed to TXT_HideWindow.\n") ;
  435.     }
  436. }
  437.  
  438.  
  439. uint TXT_LoadResources (void)
  440.  
  441. /*
  442.  *  Function :
  443.  *                  Load the template required by TEXT.
  444.  *
  445.  *  Parameters :
  446.  *                  None.
  447.  *
  448.  *  Returns :
  449.  *                  TRUE for success, FALSE for failure.
  450.  *
  451.  */
  452.  
  453. {
  454.     if (WA_LoadTemplate (TEMPLATE_FILE,
  455.                          TEMPLATE_NAME))
  456.     {
  457.         TemplateLoaded = TRUE ;
  458.         return (TRUE) ;
  459.     }
  460.     else
  461.     {
  462.         LOG_Error ("TXT: Unable to load required template.\n") ;
  463.         return (FALSE) ;
  464.     }
  465. }
  466.  
  467.  
  468. void TXT_PutText (
  469.     t_TXT_Handle  handle,
  470.     const u8     *text)
  471.  
  472. /*
  473.  *  Function :
  474.  *                  Put text to a text window.
  475.  *
  476.  *  Parameters :
  477.  *                  handle      Handle of the window to put to.
  478.  *                  text        Null-terminated text to put.
  479.  *
  480.  *  Returns :
  481.  *                  None.
  482.  *
  483.  */
  484.  
  485. {
  486.     u8              *body ;
  487.     uint             col ;
  488.     const u8        *cr ;
  489.     const u8        *current ;
  490.     u8              *dest ;
  491.     _kernel_oserror  eb ;
  492.     t_error_flags    ef ;
  493.     uint             index ;
  494.     uint             len ;
  495.     uint             more ;
  496.     t_point          origin ;
  497.     t_redraw_block   r ;
  498.     uint             result ;
  499.     uint             row ;
  500.     t_box            source ;
  501.     uint             space ;
  502.     uint             to_put ;
  503.  
  504.     /*
  505.      *  We need a little check here against recursive calls.  I know there is
  506.      *  already an external check, but there is one possibility that it won't
  507.      *  cope with.  If we got an action message from Risc-OS, and encountered
  508.      *  a problem, we may have generated a log message.  This log message will
  509.      *  eventually end up back here, and we could find ourselves trying to
  510.      *  update the window in the middle of doing something else.  Hence our
  511.      *  little check.
  512.      */
  513.     if (InEventHandler)
  514.     {
  515.         /*
  516.          *  Use an error box instead.
  517.          */
  518.         eb.errnum  = 1 ;
  519.         strncpy (eb.errmess,
  520.                  text,
  521.                  251) ;
  522.         eb.errmess [251] = '\0' ;
  523.         ef.value = 0 ;
  524.         ef.m.ok  = TRUE ;
  525.         WIMP_ReportError (&eb, ef, "TXT", &result) ;
  526.     }
  527.     else
  528.     {
  529.         if (HandleValid (handle))
  530.         {
  531.             col  = handle->col ;
  532.             row  = handle->row ;
  533.             body = (u8 *) (handle + 1) ;
  534.             current = text ;
  535.             while ((len = strlen (current)) > 0)
  536.             {
  537.                 space = handle->width - col ;
  538.                 cr = strchr (current, '\n') ;
  539.                 if (cr == NULL)
  540.                 {
  541.                     if (len > space)
  542.                     {
  543.                         to_put = space ;
  544.                     }
  545.                     else
  546.                     {
  547.                         to_put = len ;
  548.                     }
  549.                 }
  550.                 else
  551.                 {
  552.                     if ((cr - current) > space)
  553.                     {
  554.                         to_put = space ;
  555.                     }
  556.                     else
  557.                     {
  558.                         to_put = cr - current ;
  559.                     }
  560.                 }
  561.                 /*
  562.                  *  Put the characters in the buffer.
  563.                  */
  564.                 dest = body + (row * handle->width) + col ;
  565.                 for (index = 0; index < to_put; index++)
  566.                 {
  567.                     if (current [index] < ' ')
  568.                     {
  569.                         dest [index] = ' ' ;
  570.                     }
  571.                     else
  572.                     {
  573.                         dest [index] = current [index] ;
  574.                     }
  575.                 }
  576.                 if (handle->visible)
  577.                 {
  578.                     if ((handle->cursor_on) &&
  579.                         (handle->cursor_visible))
  580.                     {
  581.                         PlotCursor (handle) ;
  582.                         handle->cursor_visible = FALSE ;
  583.                     }
  584.                     /*
  585.                      *  Paint the relevant bit of screen.
  586.                      */
  587.                     r.handle = handle->window_handle ;
  588.                     r.visible_area.min.x = CHAR_WIDTH * col ;
  589.                     r.visible_area.min.y = -(CHAR_HEIGHT * (row + 1)) ;
  590.                     r.visible_area.max.x = r.visible_area.min.x + (CHAR_WIDTH * to_put) ;
  591.                     r.visible_area.max.y = r.visible_area.min.y + CHAR_HEIGHT ;
  592.                     if (LOG_OSError (WIMP_UpdateWindow (&r, &more)) == NULL)
  593.                     {
  594.                         while (more)
  595.                         {
  596.                             origin.x = r.visible_area.min.x - r.scroll_offset.x ;
  597.                             origin.y = r.visible_area.max.y - r.scroll_offset.y ;
  598.                             /*
  599.                              *  Cursor to start.
  600.                              */
  601.                             VDU (CLG) ;
  602.                             VDU_Move (origin.x + (CHAR_WIDTH * col),
  603.                                       origin.y - (CHAR_HEIGHT * row) - Y_OFFSET) ;
  604.                             for (index = 0; index < to_put; index++)
  605.                             {
  606.                                 VDU (dest [index]) ;
  607.                             }
  608.                             WIMP_GetRectangle (&r, &more) ;
  609.                         }
  610.                     }
  611.                 }
  612.                 /*
  613.                  *  Adjust the cursor position.
  614.                  */
  615.                 if (current [to_put] == '\n')
  616.                 {
  617.                     to_put++ ;
  618.                     col = 0 ;
  619.                     row++ ;
  620.                 }
  621.                 else
  622.                 {
  623.                     col += to_put ;
  624.                     if (col >= handle->width)
  625.                     {
  626.                         col = 0 ;
  627.                         row++ ;
  628.                     }
  629.                 }
  630.                 current += to_put ;
  631.                 /*
  632.                  *  Do we need to scroll?
  633.                  */
  634.                 if (row >= handle->height)
  635.                 {
  636.                     if (handle->visible)
  637.                     {
  638.                         /*
  639.                          *  All we do is tell the system to scroll by way of a WIMP_BlockCopy.
  640.                          *  Risc-OS takes care of the rest.
  641.                          */
  642.                         source.min.x = 0 ;
  643.                         source.min.y = 0 - handle->osheight ;
  644.                         source.max.x = handle->oswidth ;
  645.                         source.max.y = 0 - CHAR_HEIGHT ;
  646.                         LOG_OSError (WIMP_BlockCopy (handle->window_handle,
  647.                                                      &source,
  648.                                                      0,
  649.                                                      CHAR_HEIGHT - handle->osheight)) ;
  650.                         /*
  651.                          *  Blank out the new bottom line.
  652.                          */
  653.                         r.handle = handle->window_handle ;
  654.                         r.visible_area.min.x = 0 ;
  655.                         r.visible_area.min.y = 0 - handle->osheight ;
  656.                         r.visible_area.max.x = handle->oswidth ;
  657.                         r.visible_area.max.y = r.visible_area.min.y + CHAR_HEIGHT ;
  658.                         if (LOG_OSError (WIMP_UpdateWindow (&r, &more)) == NULL)
  659.                         {
  660.                             while (more)
  661.                             {
  662.                                 VDU (CLG) ;
  663.                                 WIMP_GetRectangle (&r, &more) ;
  664.                             }
  665.                         }
  666.                     }
  667.                     memmove (body,
  668.                              body + handle->width,
  669.                              (handle->height - 1) * handle->width) ;
  670.                     memset (body + ((handle->height - 1) * handle->width),
  671.                             ' ',
  672.                             handle->width) ;
  673.                     row-- ;
  674.                 }
  675.             }
  676.             handle->col = col ;
  677.             handle->row = row ;
  678.             if ((handle->visible) &&
  679.                 (handle->cursor_on))
  680.             {
  681.                 PlotCursor (handle) ;
  682.                 handle->cursor_visible = TRUE ;
  683.             }
  684.         }
  685.         else
  686.         {
  687.             LOG_Warning ("TXT: Invalid handle passed to TXT_PutText.\n") ;
  688.         }
  689.     }
  690. }
  691.  
  692.  
  693. void TXT_SetCursor (
  694.     t_TXT_Handle handle,
  695.     uint         row,
  696.     uint         column)
  697.  
  698. /*
  699.  *  Function :
  700.  *                  Set the cursor position in a text window.
  701.  *
  702.  *  Parameters :
  703.  *                  handle  Handle of window.
  704.  *                  row     Row to put it in.
  705.  *                  column  Column to put it in.    
  706.  *
  707.  *  Returns :
  708.  *                  None.
  709.  *
  710.  */
  711.  
  712. {
  713.     if (HandleValid (handle))
  714.     {
  715.         if (row >= handle->height)
  716.         {
  717.             LOG_Warning ("TXT: Attempt to set cursor to row %d of %d.\n") ;
  718.             row = handle->height - 1 ;
  719.         }
  720.         if (column >= handle->width)
  721.         {
  722.             LOG_Warning ("TXT: Attempt to set cursor to column %d of %d.\n") ;
  723.             column = handle->width - 1 ;
  724.         }
  725.         handle->row = row ;
  726.         handle->col = column ;
  727.     }
  728.     else
  729.     {
  730.         LOG_Warning ("TXT: Invalid handle passed to TXT_SetCursor.\n") ;
  731.     }
  732. }
  733.  
  734. /*
  735.  *============================================================================
  736.  *
  737.  *  Private routines.
  738.  *
  739.  *============================================================================
  740.  */
  741.  
  742. static void ActivateCursor (
  743.     t_TXT_Handle handle)
  744.  
  745. /*
  746.  *  Function :
  747.  *                  Activate the cursor in a window.  Should only
  748.  *                  be called if the window is visible on the screen.
  749.  *
  750.  *  Parameters :
  751.  *                  handle  Handle on the window.
  752.  *
  753.  *  Returns :
  754.  *                  None.
  755.  *
  756.  */
  757.  
  758. {
  759.     handle->cursor_visible = FALSE ;
  760.     if (WA_AlarmEvery (FLASH_INTERVAL,
  761.                        FALSE,
  762.                        TickerHandler,
  763.                        handle))
  764.     {
  765.         handle->ticker_active = TRUE ;
  766.     }
  767.     else
  768.     {
  769.         LOG_Error ("TXT: Failed to start ticker for cursor flash.\n") ;
  770.         /*
  771.          *  Use a solid cursor.
  772.          */
  773.         PlotCursor (handle) ;
  774.         handle->cursor_visible = TRUE ;
  775.     }
  776. }
  777.  
  778.  
  779. static void DeactivateCursor (
  780.     t_TXT_Handle handle)
  781.  
  782. /*
  783.  *  Function :
  784.  *                  Deactivate the cursor in a window.  Should only
  785.  *                  be called if the window is visible on the screen.
  786.  *
  787.  *  Parameters :
  788.  *                  handle  Handle on the relevant window.
  789.  *
  790.  *  Returns :
  791.  *                  None.
  792.  *
  793.  */
  794.  
  795. {
  796.     if (handle->ticker_active)
  797.     {
  798.         WA_CancelAlarm (TickerHandler, handle) ;
  799.         handle->ticker_active = FALSE ;
  800.     }
  801.     if (handle->cursor_visible)
  802.     {
  803.         PlotCursor (handle) ;
  804.         handle->cursor_visible = FALSE ;
  805.     }
  806. }
  807.  
  808.  
  809. static uint EventHandler (
  810.     t_poll_block *poll_block,
  811.     void         *reference)
  812.  
  813. /*
  814.  *  Function :
  815.  *                  Handle events for our text windows.
  816.  *
  817.  *  Parameters :
  818.  *                  poll_block  Pointer to poll block describing event.
  819.  *                  reference   Pointer to our record.
  820.  *
  821.  *  Returns :
  822.  *                  TRUE if we handled the event, FALSE otherwise.
  823.  *
  824.  */
  825.  
  826. {
  827.     t_TXTI_Record         *current ;
  828.     const _kernel_oserror *error_ptr ;
  829.     uint                   more ;
  830.     t_redraw_block         r ;
  831.     uint                   result ;
  832.  
  833.     InEventHandler = TRUE ;
  834.     result  = FALSE ;
  835.     current = reference ;
  836.     switch (poll_block->event_type)
  837.     {
  838.         case ET_RedrawRequest :
  839.             r.handle = poll_block->data.ob.window_handle ;
  840.             error_ptr = WIMP_RedrawWindow (&r, &more) ;
  841.             if (error_ptr == NULL)
  842.             {
  843.                 while (more)
  844.                 {
  845.                     RedrawWindow (current, &r) ;
  846.                     WIMP_GetRectangle (&r, &more) ;
  847.                 }
  848.             }
  849.             else
  850.             {
  851.                 LOG_OSError (error_ptr) ;
  852.             }
  853.             result = TRUE ;
  854.             break ;
  855.  
  856.         case ET_OpenRequest :
  857.             LOG_OSError (WIMP_OpenWindow (&poll_block->data.ob)) ;
  858.             result = TRUE ;
  859.             break ;
  860.  
  861.         case ET_CloseRequest :
  862.             LOG_OSError (WIMP_CloseWindow (current->window_handle)) ;
  863.             if (current->visible)
  864.             {
  865.                 current->visible = FALSE ;
  866.                 if (current->cursor_on)
  867.                 {
  868.                     DeactivateCursor (current) ;
  869.                 }
  870.             }
  871.             result = TRUE ;
  872.             break ;
  873.  
  874.     }
  875.     InEventHandler = FALSE ;
  876.     return (result) ;
  877. }
  878.  
  879.  
  880. static uint HandleValid (
  881.     t_TXT_Handle handle)
  882.  
  883. /*
  884.  *  Function :
  885.  *                  Check whether a window handle is valid.
  886.  *
  887.  *  Parameters :
  888.  *                  handle      Handle to check.
  889.  *
  890.  *  Returns :
  891.  *                  TRUE if it is, FALSE if it isn't.
  892.  *
  893.  */
  894.  
  895. {
  896.     return (LL_InList (&RecordAnchor, &(handle->header))) ;
  897. }
  898.  
  899.  
  900. static void PlotCursor (
  901.     t_TXT_Handle handle)
  902.  
  903. /*
  904.  *  Function :
  905.  *                  Plot the cursor in a window.  This is done using
  906.  *                  a block XOR, so this routine toggles it - off if on
  907.  *                  and on if off.
  908.  *
  909.  *  Parameters :
  910.  *                  handle  Handle of the window to plot in.
  911.  *
  912.  *  Returns :
  913.  *                  None.
  914.  *
  915.  */
  916.  
  917. {
  918.     uint           more ;
  919.     t_redraw_block r ;
  920.  
  921.     r.handle = handle->window_handle ;
  922.     r.visible_area.min.x = CHAR_WIDTH * handle->col ;
  923.     r.visible_area.min.y = -(CHAR_HEIGHT * (handle->row + 1)) ;
  924.     r.visible_area.max.x = r.visible_area.min.x + CHAR_WIDTH ;
  925.     r.visible_area.max.y = r.visible_area.min.y + CHAR_HEIGHT ;
  926.     if (LOG_OSError (WIMP_UpdateWindow (&r, &more)) == NULL)
  927.     {
  928.         while (more)
  929.         {
  930.             /*
  931.              *  XOR one character position.
  932.              */
  933.             VDU_Gcol (3, 135) ;
  934.             VDU (CLG) ;
  935.             WIMP_GetRectangle (&r, &more) ;
  936.         }
  937.     }
  938. }
  939.  
  940.  
  941. static void RedrawWindow (
  942.     t_TXT_Handle    handle,
  943.     t_redraw_block *r)
  944.  
  945. /*
  946.  *  Function :
  947.  *                  Redraw part or all of a window.
  948.  *
  949.  *  Parameters :
  950.  *                  handle  Our handle on window to redraw.
  951.  *                  r       Redraw block defining required area.
  952.  *
  953.  *  Returns :
  954.  *                  None.
  955.  *
  956.  */
  957.  
  958. {
  959.     const u8 *body ;
  960.     uint      col ;
  961.     const u8 *line ;
  962.     sint      maxrow ;
  963.     sint      minrow ;
  964.     t_point   origin ;
  965.     sint      row ;
  966.     t_box     vwa ;
  967.  
  968.     origin.x = r->visible_area.min.x - r->scroll_offset.x ;
  969.     origin.y = r->visible_area.max.y - r->scroll_offset.y ;
  970.     body = (u8 *) (handle + 1) ;
  971.     /*
  972.      *  Calculate which rows require re-drawing.
  973.      */
  974.     vwa.min.x = r->graphics_window.min.x - r->visible_area.min.x + r->scroll_offset.x ;
  975.     vwa.max.x = vwa.min.x + (r->graphics_window.max.x - r->graphics_window.min.x) ;
  976.     vwa.max.y = r->graphics_window.max.y - r->visible_area.max.y + r->scroll_offset.y ;
  977.     vwa.min.y = vwa.max.y - (r->graphics_window.max.y - r->graphics_window.min.y) ;
  978.     minrow = (-vwa.max.y) / CHAR_HEIGHT ;
  979.     if (vwa.min.y == 0)
  980.     {
  981.         maxrow = -1 ;
  982.     }
  983.     else
  984.     {
  985.         maxrow = ((- vwa.min.y - 1) / CHAR_HEIGHT) ;
  986.     }
  987.     if (maxrow >= (sint) handle->height)
  988.     {
  989.         maxrow = (sint) (handle->height - 1) ;
  990.     }
  991.     for (row = minrow; row <= maxrow; row++)
  992.     {
  993.         /*
  994.          *  Cursor to start.
  995.          */
  996.         VDU_Move (origin.x, origin.y - (CHAR_HEIGHT * row) - Y_OFFSET) ;
  997.         line = body + (row * handle->width) ;
  998.         for (col = 0; col < handle->width; col++)
  999.         {
  1000.             VDU (line [col]) ;
  1001.         }
  1002.     }
  1003.     /*
  1004.      *  Check the cursor position.
  1005.      */
  1006.     if ((handle->cursor_on) &&
  1007.         (handle->cursor_visible) &&
  1008.         (handle->row >= minrow) &&
  1009.         (handle->row <= maxrow))
  1010.     {
  1011.         /*
  1012.          *  Redo the cursor position.
  1013.          */
  1014.         VDU_Gcol (3, 7) ;
  1015.         VDU_Move (origin.x + (CHAR_WIDTH * handle->col),
  1016.                   origin.y - (CHAR_HEIGHT * (handle->row + 1))) ;
  1017.         VDU_Plot (97, CHAR_WIDTH - 1, CHAR_HEIGHT - 1) ;
  1018.     }
  1019. }
  1020.  
  1021.  
  1022. static void TickerHandler (
  1023.     void *reference)
  1024.  
  1025. /*
  1026.  *  Function :
  1027.  *                  Flash the cursor for a window.
  1028.  *
  1029.  *  Parameters :
  1030.  *                  reference   Window handle for the relevant window.
  1031.  *
  1032.  *  Returns :
  1033.  *                  None.
  1034.  *
  1035.  */
  1036.  
  1037. {
  1038.     t_TXT_Handle handle ;
  1039.  
  1040.     handle = reference ;
  1041.     PlotCursor (handle) ;
  1042.     handle->cursor_visible = !handle->cursor_visible ;
  1043. }
  1044.