home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 2 / AUCD2.iso / program / vista.arc / c / window < prev    next >
Text File  |  1996-02-01  |  25KB  |  1,083 lines

  1. // **************************************************************************
  2. //                     Copyright 1996 David Allison
  3. //
  4. //             VV    VV    IIIIII     SSSSS     TTTTTT       AA
  5. //             VV    VV      II      SS           TT       AA  AA
  6. //             VV    VV      II        SSSS       TT      AA    AA
  7. //              VV  VV       II           SS      TT      AAAAAAAA
  8. //                VV       IIIIII     SSSS        TT      AA    AA
  9. //
  10. //                    MULTI-THREADED C++ WIMP CLASS LIBRARY
  11. //                                for RISC OS
  12. // **************************************************************************
  13. //
  14. //             P U B L I C    D O M A I N    L I C E N C E
  15. //             -------------------------------------------
  16. //
  17. //     This library is copyright. You may not sell the library for
  18. //     profit, but you may sell products which use it providing
  19. //     those products are presented as executable code and are not
  20. //     libraries themselves.  The library is supplied without any
  21. //     warranty and the copyright owner cannot be held responsible for
  22. //     damage resulting from failure of any part of this library.
  23. //
  24. //          See the User Manual for details of the licence.
  25. //
  26. // *************************************************************************
  27.  
  28. //
  29. // c.window
  30. //
  31.  
  32. #include "Vista:task.h"
  33. #include "Vista:window.h"
  34. #include <swis.h>
  35. #include <kernel.h>
  36. #include <stdarg.h>
  37. #include <stdio.h>
  38.  
  39. Window::Window (Task *tsk, char *tname, char *m)
  40.    {
  41.    void *defn ;
  42.    _kernel_swi_regs r ;
  43.    _kernel_oserror *e ;
  44.    int block[9] ;
  45.  
  46.    task = tsk ;
  47.    //t->print ("creating window, tsk = %x, name = %s\n",tsk,tname) ;
  48.    if ((defn = tsk->find_template (tname)) == NULL)
  49.       throw ("No such Template") ;
  50.    r.r[1] = (int)defn ;
  51.    if ((e = _kernel_swi (Wimp_CreateWindow, &r, &r)) != NULL)
  52.       throw (e) ;
  53.    handle = r.r[0] ;
  54.    template_data = defn ;
  55.    block[0] = handle ;
  56.    r.r[1] = (int)block ;
  57.    if ((e = _kernel_swi (Wimp_GetWindowState, &r, &r)) != NULL)
  58.       throw (e) ;
  59.    x0 = block[1] ;
  60.    y0 = block[2] ;
  61.    x1 = block[3] ;
  62.    y1 = block[4] ;
  63.    scx = block[5] ;
  64.    scy = block[6] ;
  65.    prev = NULL ;
  66.    next = NULL ;
  67.    //::print ("window handle = %x",handle) ;
  68.    tsk->add_window(this) ;            // add the window to the task
  69.    is_open = FALSE ;
  70.    icons = NULL ;
  71.    last_icon = NULL ;
  72.    objects = NULL ;
  73.    last_object = NULL ;
  74.    if (m == NULL)
  75.       default_menu = NULL ;
  76.    else
  77.       {
  78.       default_menu = tsk->find_menu (m) ;
  79.       if (default_menu == NULL)
  80.       throw ("Unknown menu") ;
  81.       }
  82.    sub_windows = NULL ;           // no subwindows
  83.    parent = NULL ;                // no parent
  84.    tracker = NULL ;
  85.    deleting = false ;
  86.    }
  87.  
  88. Window::Window (Window *w, char *tname, int anchor, char *m)
  89.    {
  90.    void *defn ;
  91.    _kernel_swi_regs r ;
  92.    _kernel_oserror *e ;
  93.    int block[9] ;
  94.  
  95. //   ::print ("creating sub window, name = %s\n",tname) ;
  96.    this->anchor = anchor ;
  97.    task = w->task ;
  98.    if ((defn = task->find_template (tname)) == NULL)
  99.       throw ("No such Template") ;
  100.    r.r[1] = (int)defn ;
  101.    if ((e = _kernel_swi (Wimp_CreateWindow, &r, &r)) != NULL)
  102.       throw (e) ;
  103.    handle = r.r[0] ;
  104.    template_data = defn ;
  105.    block[0] = handle ;
  106.    r.r[1] = (int)block ;
  107.    if ((e = _kernel_swi (Wimp_GetWindowState, &r, &r)) != NULL)
  108.       throw (e) ;
  109. // if the window is anchored then the coords are relative to the top of the parent
  110. // window, otherwise they are relative to the bottom
  111.    switch (anchor)
  112.       {
  113.       case A_NONE:
  114.       case A_BOTTOM:
  115.          x0 = block[1] - w->x0 ;
  116.          y0 = block[2] - w->y0 ;
  117.          x1 = block[3] - w->x0 ;
  118.          y1 = block[4] - w->y0 ;
  119.          break ;
  120.       case A_LEFT:
  121.       case A_TOP:
  122.          x0 = block[1] - w->x0 ;
  123.          y0 = block[2] - w->y1 ;
  124.          x1 = block[3] - w->x0 ;
  125.          y1 = block[4] - w->y1 ;
  126.          break ;
  127.       case A_RIGHT:
  128.          x0 = block[1] - w->x1 ;
  129.          y0 = block[2] - w->y1 ;
  130.          x1 = block[3] - w->x1 ;
  131.          y1 = block[4] - w->y1 ;
  132.          break ;
  133.       }
  134.  
  135.    scx = block[5] ;
  136.    scy = block[6] ;
  137.  
  138.  
  139.    //::print ("window handle = %x",handle) ;
  140.    prev = NULL ;
  141.    next = NULL ;
  142.    w->add_sub_window(this) ;            // add the window to the task
  143.    is_open = FALSE ;
  144.    icons = NULL ;
  145.    last_icon = NULL ;
  146.    objects = NULL ;
  147.    last_object = NULL ;
  148.    if (m == NULL)
  149.       default_menu = NULL ;
  150.    else
  151.       {
  152.       default_menu = task->find_menu (m) ;
  153.       if (default_menu == NULL)
  154.       throw ("Unknown menu") ;
  155.       }
  156.    sub_windows = NULL ;           // no subwindows
  157.    tracker = NULL ;
  158.    deleting = false ;
  159.    }
  160.  
  161. Window::~Window()
  162.    {
  163.    Icon *ni ;
  164.    Window *nw ;
  165.    Object *no ;
  166.  
  167.    deleting = true ;
  168.    if (is_open)
  169.       do_close() ;
  170.    for (Icon *i = icons ; i != NULL ; i = ni)
  171.       {
  172.       ni = i->next ;
  173.       delete i ;
  174.       }
  175.    for (Window *w = sub_windows ; w != NULL ; w = nw)
  176.       {
  177.       nw = w->next ;
  178.       delete w ;
  179.       }
  180.    for (Object *o = objects ; o != NULL ; o = no)
  181.       {
  182.       no = o->next ;
  183.       delete o ;
  184.       }
  185.    task->remove_window (this) ;
  186.    if (parent != NULL)
  187.       parent->remove_sub_window (this) ;
  188.    if (tracker != NULL)
  189.       delete tracker ;
  190.    task->free_template(template_data) ;         // free up the definition data
  191.    }
  192.  
  193. //
  194. // get a sub window's x0 coordinate in screen coordinates
  195. //
  196.  
  197. int Window::subx0(Window *sub)
  198.    {
  199.    int myx0 ;                 // my x0 coord
  200.    if (parent != NULL)
  201.       myx0 = parent->subx0(this) ;
  202.    else
  203.       myx0 = x0 ;
  204.    switch (sub->anchor)
  205.       {
  206.       case A_NONE:
  207.       case A_BOTTOM:
  208.       default:
  209.          return myx0 + sub->x0 ;
  210.       case A_LEFT:
  211.       case A_TOP:
  212.          return myx0 + sub->x0 ;
  213.       case A_RIGHT:
  214.          return myx0 + (x1-x0) + sub->x0 ;  // == myx1 + sub->x0
  215.       }
  216.    }
  217.  
  218. //
  219. // get the y1 coordinate for a sub window in screen coordinates
  220. //
  221.  
  222.  
  223. int Window::suby1(Window *sub)
  224.    {
  225.    int myy1 ;                 // my y1 coord
  226.    if (parent != NULL)
  227.       myy1 = parent->suby1(this) ;
  228.    else
  229.       myy1 = y1 ;
  230.    switch (sub->anchor)
  231.       {
  232.       case A_NONE:
  233.       case A_BOTTOM:
  234.       default:
  235.          return myy1 - (y1-y0) + sub->y1 ;   // == myy0 + sub->y1
  236.       case A_LEFT:
  237.       case A_TOP:
  238.          return myy1 + sub->y1 ;
  239.       case A_RIGHT:
  240.          return myy1 + sub->y1 ;
  241.       }
  242.    }
  243.  
  244.  
  245. void Window::add_icon(Icon *i)
  246.    {
  247.    i->next = NULL ;
  248.    if (icons == NULL)
  249.       icons = last_icon = i ;
  250.    else
  251.       {
  252.       last_icon->next = i ;
  253.       i->prev = last_icon ;
  254.       last_icon = i ;
  255.       }
  256.    }
  257.  
  258. void Window::remove_icon (Icon *i)
  259.    {
  260.    if (i->prev == NULL)
  261.       icons = i->next ;
  262.    else
  263.       i->prev->next = i->next ;
  264.    if (i->next == NULL)
  265.       last_icon = i->prev ;
  266.    else
  267.       i->next->prev = i->prev ;
  268.    }
  269.  
  270. void Window::add_object(Object *o)
  271.    {
  272.    Object *obj = objects ;
  273.    while (obj != NULL && obj->priority < o->priority)  // find position
  274.       obj = obj->next ;
  275.    o->next = obj ;
  276.    if (obj == NULL)              // at end of queue
  277.       o->prev = last_object ;
  278.    else
  279.       o->prev = obj->prev ;
  280.    if (o->prev == NULL)
  281.       objects = o ;
  282.    else
  283.       o->prev->next = o ;
  284.    if (o->next == NULL)
  285.       last_object = o ;
  286.    else
  287.       o->next->prev = o ;
  288.    }
  289.  
  290. void Window::remove_object (Object *o)
  291.    {
  292.    if (o->prev == NULL)
  293.       objects = o->next ;
  294.    else
  295.       o->prev->next = o->next ;
  296.    if (o->next == NULL)
  297.       last_object = o->prev ;
  298.    else
  299.       o->next->prev = o->prev ;
  300.    }
  301.  
  302. void Window::add_sub_window (Window *w)
  303.    {
  304.    if (sub_windows == NULL)
  305.       sub_windows = last_sub_window = w ;
  306.    else
  307.       {
  308.       last_sub_window->next = w ;
  309.       w->prev = last_sub_window ;
  310.       last_sub_window = w ;
  311.       }
  312.    w->parent = this ;
  313.    }
  314.  
  315. void Window::remove_sub_window (Window *w)
  316.    {
  317.    if (w->prev == NULL)
  318.       sub_windows = w->next ;
  319.    else
  320.       w->prev->next = w->next ;
  321.    if (w->next == NULL)
  322.       last_sub_window = w->prev ;
  323.    else
  324.       w->next->prev = w->prev ;
  325.    w->parent = NULL ;
  326.    }
  327.  
  328. void Window::do_open(int x0, int y0, int x1, int y1, int scx, int scy, int behind)
  329.    {
  330.    int block[8] ;
  331.    _kernel_swi_regs r ;
  332.    _kernel_oserror *e ;
  333.  
  334.    if (parent == NULL)         // top window? - set coords
  335.       {
  336.       this->x0 = x0 ;
  337.       this->y0 = y0 ;
  338.       this->x1 = x1 ;
  339.       this->y1 = y1 ;
  340.       }
  341.    this->scx = scx ;          // set scroll positions
  342.    this->scy = scy ;
  343.    for (Window *w = sub_windows ; w != NULL ; w = w->next)
  344.       w->do_open(behind) ;
  345.    block[0] = handle ;
  346.    block[1] = x0 ;
  347.    block[2] = y0 ;
  348.    block[3] = x1 ;
  349.    block[4] = y1 ;
  350.    block[5] = scx ;
  351.    block[6] = scy ;
  352.    if (sub_windows != NULL)
  353.       block[7] = sub_windows->handle ;   // open behind first subwindow
  354.    else
  355.       block[7] = behind ;
  356.    r.r[1] = (int)block ;
  357.    if ((e = _kernel_swi (Wimp_OpenWindow, &r, &r)) != NULL)
  358.       throw (e) ;
  359.    is_open = TRUE ;
  360.    }
  361.  
  362. void Window::do_open(int behind)
  363.    {
  364.    int block[9] ;
  365.    _kernel_swi_regs r ;
  366.    _kernel_oserror *e ;
  367.  
  368.    block[0] = handle ;
  369.    for (Window *w = sub_windows ; w != NULL ; w = w->next)
  370.       w->do_open(behind) ;
  371.    if (parent == NULL)           // top window
  372.       {
  373.       r.r[1] = (int)block ;
  374.       if ((e = _kernel_swi (Wimp_GetWindowState, &r, &r)) != NULL)
  375.          throw (e) ;
  376.       }
  377.    else
  378.       {                        // sub window
  379.       switch (anchor)
  380.          {
  381.          case A_NONE:
  382.             block[1] = parent->x0 + x0 - parent->scx ;
  383.             block[2] = parent->y0 + y0 - parent->scy ;
  384.             block[3] = parent->x0 + x1 - parent->scx ;
  385.             block[4] = parent->y0 + y1 - parent->scy ;
  386.             break ;
  387.          case A_LEFT:
  388.          case A_TOP:
  389.             block[1] = parent->x0 + x0 ;
  390.             block[2] = parent->y1 + y0 ;
  391.             block[3] = parent->x0 + x1 ;
  392.             block[4] = parent->y1 + y1 ;
  393.             break ;
  394.          case A_RIGHT:
  395.             block[1] = parent->x1 + x0 ;
  396.             block[2] = parent->y1 + y0 ;
  397.             block[3] = parent->x1 + x1 ;
  398.             block[4] = parent->y1 + y1 ;
  399.             break ;
  400.          case A_BOTTOM:
  401.             block[1] = parent->x0 + x0 ;
  402.             block[2] = parent->y0 + y0 ;
  403.             block[3] = parent->x0 + x1 ;
  404.             block[4] = parent->y0 + y1 ;
  405.             break ;
  406.          }
  407.       block[5] = scx ;
  408.       block[6] = scy ;
  409.       }
  410.    if (sub_windows != NULL)
  411.       block[7] = sub_windows->handle ;   // open behind first subwindow
  412.    else
  413.       block[7] = behind ;             // open behind that given
  414.    r.r[1] = (int)block ;
  415.    if ((e = _kernel_swi (Wimp_OpenWindow, &r, &r)) != NULL)
  416.       throw (e) ;
  417.    is_open = TRUE ;
  418.    }
  419.  
  420. void Window::do_open(int x0, int y0, int behind)
  421.    {
  422.    int block[8] ;
  423.    _kernel_swi_regs r ;
  424.    _kernel_oserror *e ;
  425.    int xdiff, ydiff ;
  426.  
  427.    r.r[1] = (int)block ;
  428.    block[0] = handle ;
  429.    if ((e = _kernel_swi (Wimp_GetWindowState, &r, &r)) != NULL)
  430.       throw (e) ;
  431.    xdiff = block[3] - block[1] ;
  432.    ydiff = block[4] - block[2] ;
  433.  
  434.    this->x0 = x0 ;
  435.    this->y0 = y0 ;
  436.    this->x1 = x0 + xdiff ;
  437.    this->y1 = y0 + ydiff ;
  438.    this->scx = block[5] ;          // set scroll positions
  439.    this->scy = block[6] ;
  440.    block[1] = this->x0 ;
  441.    block[2] = this->y0 ;
  442.    block[3] = this->x1 ;
  443.    block[4] = this->y1 ;
  444.    for (Window *w = sub_windows ; w != NULL ; w = w->next)
  445.       w->do_open(behind) ;
  446.    if (sub_windows != NULL)
  447.       block[7] = sub_windows->handle ;   // open behind first subwindow
  448.    else
  449.       block[7] = behind ;
  450.    r.r[1] = (int)block ;
  451.    if ((e = _kernel_swi (Wimp_OpenWindow, &r, &r)) != NULL)
  452.       throw (e) ;
  453.    is_open = TRUE ;
  454.    }
  455.  
  456.  
  457. void Window::do_close()
  458.    {
  459.    int block ; ;
  460.    _kernel_swi_regs r ;
  461.    _kernel_oserror *e ;
  462.  
  463.    for (Window *w = sub_windows ; w != NULL ; w = w->next)
  464.       w->do_close() ;
  465.    block = handle ;
  466.    r.r[1] = (int)&block ;
  467.    if ((e = _kernel_swi (Wimp_CloseWindow, &r, &r)) != NULL)
  468.       throw (e) ;
  469.    is_open = FALSE ;
  470.    }
  471.  
  472. //
  473. // redraw part of a window
  474. //
  475.  
  476.  
  477. void Window::do_redraw(int x0, int y0, int x1, int y1)
  478.    {
  479.    _kernel_swi_regs r ;
  480.    _kernel_oserror *e ;
  481.  
  482.    r.r[0] = handle ;
  483.    r.r[1] = x0 ;
  484.    r.r[2] = y0 ;
  485.    r.r[3] = x1 ;
  486.    r.r[4] = y1 ;
  487.    if ((e = _kernel_swi (Wimp_ForceRedraw, &r, &r)) != NULL)
  488.       throw (e) ;
  489.    }
  490.  
  491. //
  492. // redraw all of a window
  493. //
  494.  
  495. void Window::do_redraw()
  496.    {
  497.    _kernel_swi_regs r ;
  498.    _kernel_oserror *e ;
  499.    int block[30] ;
  500.  
  501.    block[0] = handle ;
  502.    r.r[1] = ((int)block) | 1 ;    // dont read icons
  503.    if ((e = _kernel_swi (Wimp_GetWindowInfo, &r, &r)) != NULL)
  504.       throw (e) ;
  505.    r.r[0] = handle ;
  506.    r.r[1] = block[11] ;
  507.    r.r[2] = block[12] ;
  508.    r.r[3] = block[13] ;
  509.    r.r[4] = block[14] ;
  510.    if ((e = _kernel_swi (Wimp_ForceRedraw, &r, &r)) != NULL)
  511.       throw (e) ;
  512.    }
  513.  
  514. //
  515. // update a rectangle of the window given its window coords
  516. //
  517.  
  518. void Window::do_update(int x0, int y0, int x1, int y1)
  519.    {
  520.    int block[11] ;
  521.    _kernel_swi_regs r ;
  522.    _kernel_oserror *e ;
  523.    Object *object ;
  524.    r.r[1] = (int)block ;
  525.    block[0] = handle ;
  526.    task->enter_critical() ;
  527.    if ((e = _kernel_swi (Wimp_UpdateWindow, &r, &r)) != NULL)
  528.       {
  529.       task->exit_critical() ;
  530.       throw (e) ;
  531.       }
  532.    while (r.r[0] != 0)
  533.       {
  534.       for (object = objects ; object != NULL ; object = object->next)
  535.          object->update(block[1], block[2], block[3], block[4]) ;
  536.       if ((e = _kernel_swi (Wimp_GetRectangle, &r, &r)) != NULL)
  537.          {
  538.          task->exit_critical() ;
  539.          throw (e) ;
  540.          }
  541.       }
  542.    task->exit_critical() ;
  543.    }
  544.  
  545. //
  546. // update the whole window
  547. //
  548.  
  549. void Window::do_update()
  550.    {
  551.    Info *inf = info() ;
  552.    int width, height ;
  553.    width = inf->box.x1 - inf->box.x0 ;
  554.    height = inf->box.y1 - inf->box.y0 ;
  555.    do_update (0, -height, width, 0) ;
  556.    }
  557.  
  558.  
  559. void Window::do_drag (int type, int x0, int y0, int x1, int y1,
  560.                       int px0, int py0, int px1, int py1)
  561.    {
  562.    _kernel_swi_regs r ;
  563.    _kernel_oserror *e ;
  564.    int block[40] ;
  565.  
  566.    block[0] = handle ;
  567.    block[1] = type ;
  568.    block[2] = x0 ;
  569.    block[3] = y0 ;
  570.    block[4] = x1 ;
  571.    block[5] = y1 ;
  572.    if (px0 == -1)
  573.       {
  574.       block[6] = 0 ;
  575.       block[7] = 0 ;
  576.       block[8] = 30000 ;
  577.       block[9] = 30000 ;
  578.       }
  579.    else
  580.       {
  581.       block[6] = px0 ;
  582.       block[7] = py0 ;
  583.       block[8] = px1 ;
  584.       block[9] = py1 ;
  585.       }
  586.    r.r[1] = (int)block ;
  587.    if ((e = _kernel_swi (Wimp_DragBox, &r, &r)) != NULL)
  588.       throw (e) ;
  589.    }
  590.  
  591.  
  592. void Window::do_drag (char *sprite)
  593.    {
  594.    _kernel_swi_regs r ;
  595.    _kernel_oserror *e ;
  596.    int block[5] ;
  597.    int x, y ;
  598.  
  599.    r.r[1] = (int)block ;
  600.    _kernel_swi (Wimp_GetPointerInfo, &r, &r) ;        // read pointer position
  601.    x = block[0] ;
  602.    y = block[1] ;
  603.    r.r[0] = 0xc5 ;
  604.    r.r[1] = 1 ;
  605.    r.r[2] = (int)sprite ;
  606.    r.r[3] = (int)block ;
  607.    block[0] = x - 100 ;
  608.    block[1] = y - 100 ;
  609.    block[2] = x + 100 ;
  610.    block[3] = y + 100 ;
  611.    if ((e = _kernel_swi (DragASprite_Start, &r, &r)) != NULL)
  612.       throw (e) ;
  613.    }
  614.  
  615. void Window::do_drag (char *sprite, int x0, int y0, int x1, int y1, int flags,
  616.                             int px0, int py0,
  617.                             int px1, int py1)
  618.    {
  619.    _kernel_swi_regs r ;
  620.    _kernel_oserror *e ;
  621.    int block1[4] ;
  622.    int block2[4] ;
  623.    int x, y ;
  624.  
  625.    r.r[0] = flags ;
  626.    r.r[1] = 1 ;
  627.    r.r[2] = (int)sprite ;
  628.    r.r[3] = (int)block1 ;
  629.    r.r[4] = (int)block2 ;
  630.    block1[0] = x0 ;
  631.    block1[1] = y0 ;
  632.    block1[2] = x1 ;
  633.    block1[3] = y1 ;
  634.    block2[0] = px0 ;
  635.    block2[1] = py0 ;
  636.    block2[2] = px1 ;
  637.    block2[3] = py1 ;
  638.    if ((e = _kernel_swi (DragASprite_Start, &r, &r)) != NULL)
  639.       throw (e) ;
  640.    }
  641.  
  642.  
  643. Window::State *Window::state()
  644.    {
  645.    _kernel_swi_regs r ;
  646.    _kernel_oserror *e ;
  647.    wstate.handle = handle ;
  648.    r.r[1] = (int)&wstate ;
  649.    if ((e = _kernel_swi (Wimp_GetWindowState, &r, &r)) != NULL)
  650.       throw (e) ;
  651.    return &wstate ;
  652.    }
  653.  
  654. Window::Info *Window::info()
  655.    {
  656.    winfo.handle = handle ;
  657.    _kernel_swi_regs r ;
  658.    _kernel_oserror *e ;
  659.    r.r[1] = ((int)&winfo) | 1 ;        // no icons
  660.    if ((e = _kernel_swi (Wimp_GetWindowInfo, &r, &r)) != NULL)
  661.       throw (e) ;
  662.    return &winfo ;
  663.    }
  664.  
  665. void Window::set_extent(int x0, int y0, int x1, int y1)
  666.    {
  667.    int block[4] ;
  668.    _kernel_swi_regs r ;
  669.    _kernel_oserror *e ;
  670.    r.r[0] = handle ;
  671.    r.r[1] = (int)block ;
  672.    block[0] = x0 ;
  673.    block[1] = y0 ;
  674.    block[2] = x1 ;
  675.    block[3] = y1 ;
  676.    if ((e = _kernel_swi (Wimp_SetExtent, &r, &r)) != NULL)
  677.       throw (e) ;
  678.    }
  679.  
  680. void Window::set_extent(int width, int height)
  681.    {
  682.    Info *inf = info() ;
  683.    int block[4] ;
  684.    _kernel_swi_regs r ;
  685.    _kernel_oserror *e ;
  686.    r.r[0] = handle ;
  687.    r.r[1] = (int)block ;
  688.    block[0] = inf->extent.x0 ;
  689.    block[1] = inf->extent.y1 - height ;
  690.    block[2] = inf->extent.x0 + width ;
  691.    block[3] = inf->extent.y1 ;
  692.    if ((e = _kernel_swi (Wimp_SetExtent, &r, &r)) != NULL)
  693.       throw (e) ;
  694.    }
  695.  
  696. void Window::set_width(int x0, int x1)
  697.    {
  698.    Info *inf = info() ;
  699.    int block[4] ;
  700.    _kernel_swi_regs r ;
  701.    _kernel_oserror *e ;
  702.    r.r[0] = handle ;
  703.    r.r[1] = (int)block ;
  704.    block[0] = x0 ;
  705.    block[1] = inf->extent.y0 ;
  706.    block[2] = x1 ;
  707.    block[3] = inf->extent.y1 ;
  708.    if ((e = _kernel_swi (Wimp_SetExtent, &r, &r)) != NULL)
  709.       throw (e) ;
  710.    }
  711.  
  712. void Window::set_height(int y0, int y1)
  713.    {
  714.    Info *inf = info() ;
  715.    int block[4] ;
  716.    _kernel_swi_regs r ;
  717.    _kernel_oserror *e ;
  718.    r.r[0] = handle ;
  719.    r.r[1] = (int)block ;
  720.    block[0] = inf->extent.x0 ;
  721.    block[1] = y0 ;
  722.    block[2] = inf->extent.x1 ;
  723.    block[3] = y1 ;
  724.    if ((e = _kernel_swi (Wimp_SetExtent, &r, &r)) != NULL)
  725.       throw (e) ;
  726.    }
  727.  
  728. void Window::set_width(int width)
  729.    {
  730.    Info *inf = info() ;
  731.    int block[4] ;
  732.    _kernel_swi_regs r ;
  733.    _kernel_oserror *e ;
  734.    r.r[0] = handle ;
  735.    r.r[1] = (int)block ;
  736.    block[0] = inf->extent.x0 ;
  737.    block[1] = inf->extent.y0 ;
  738.    block[2] = inf->extent.x0 + width ;
  739.    block[3] = inf->extent.y1 ;
  740.    if ((e = _kernel_swi (Wimp_SetExtent, &r, &r)) != NULL)
  741.       throw (e) ;
  742.    }
  743.  
  744. void Window::set_height(int height)
  745.    {
  746.    Info *inf = info() ;
  747.    int block[4] ;
  748.    _kernel_swi_regs r ;
  749.    _kernel_oserror *e ;
  750.    r.r[0] = handle ;
  751.    r.r[1] = (int)block ;
  752.    block[0] = inf->extent.x0 ;
  753.    block[1] = inf->extent.y1 - height ;
  754.    block[2] = inf->extent.x1 ;
  755.    block[3] = inf->extent.y1 ;
  756.    if ((e = _kernel_swi (Wimp_SetExtent, &r, &r)) != NULL)
  757.       throw (e) ;
  758.    }
  759.  
  760. void Window::get_outline(int &x0, int &y0, int &x1, int &y1)
  761.    {
  762.    int block[5] ;
  763.    _kernel_swi_regs r ;
  764.    _kernel_oserror *e ;
  765.    r.r[1] = (int)block ;
  766.    block[0] = handle ;
  767.    if ((e = _kernel_swi (Wimp_GetWindowOutline, &r, &r)) != NULL)
  768.       throw (e) ;
  769.    x0 = block[1] ;
  770.    y0 = block[2] ;
  771.    x1 = block[3] ;
  772.    y1 = block[4] ;
  773.    }
  774.  
  775. void Window::read_position()
  776.    {
  777.    _kernel_swi_regs r ;
  778.    _kernel_oserror *e ;
  779.    int block[9] ;
  780.  
  781.    block[0] = handle ;
  782.    r.r[1] = (int)block ;
  783.    if ((e = _kernel_swi (Wimp_GetWindowState, &r, &r)) != NULL)
  784.       throw (e) ;
  785.    x0 = block[1] ;
  786.    y0 = block[2] ;
  787.    x1 = block[3] ;
  788.    y1 = block[4] ;
  789.    scx = block[5] ;
  790.    scy = block[6] ;
  791.    }
  792.  
  793. void Window::set_title (char *format ...)
  794.    {
  795.    _kernel_swi_regs r ;
  796.    _kernel_oserror *e ;
  797.    Info *inf = info() ;
  798.    va_list ap ;
  799.    va_start (ap, format) ;
  800. //   ::print ("info = %x\n",&inf) ;
  801. //   ::print ("printing to %x",inf.title.indirecttext.buffer) ;
  802.    vsprintf (inf->title.indirecttext.buffer, format, ap) ;
  803.    r.r[0] = -1 ;
  804.    r.r[1] = inf->box.x0 ;
  805.    r.r[2] = inf->box.y1 ;
  806.    r.r[3] = inf->box.x1 ;
  807.    r.r[4] = inf->box.y1 + 36 ;
  808.    if ((e = _kernel_swi (Wimp_ForceRedraw, &r, &r)) != NULL)
  809.       throw (e) ;
  810.    }
  811.  
  812. char *Window::title ()
  813.    {
  814.    Info *inf = info() ;
  815.    return inf->title.indirecttext.buffer ;
  816.    }
  817.  
  818.  
  819. void Window::redraw()
  820.    {
  821.    int block[11] ;
  822.    _kernel_swi_regs r ;
  823.    _kernel_oserror *e ;
  824.    Object *object ;
  825.    int wx0, wy0, wx1, wy1 ;    // work area coords
  826.    int scx, scy ;
  827.    int gx0, gy0, gx1, gy1 ;
  828.    int minx, maxy ;
  829.    r.r[1] = (int)block ;
  830.    block[0] = handle ;
  831.    task->enter_critical() ;
  832.    if ((e = _kernel_swi (Wimp_RedrawWindow, &r, &r)) != NULL)
  833.       {
  834.       task->exit_critical() ;
  835.       throw (e) ;
  836.       }
  837.    if (r.r[0] != 0)
  838.       {
  839.       if (parent != NULL)
  840.          {
  841.          x0 = block[1] - parent->x0 ;
  842.          y0 = block[2] - parent->y0 ;
  843.          x1 = block[3] - parent->x0 ;
  844.          y1 = block[4] - parent->y0 ;
  845.          }
  846.       else
  847.          {
  848.          x0 = block[1] ;
  849.          y0 = block[2] ;
  850.          x1 = block[3] ;
  851.          y1 = block[4] ;
  852.          }
  853.       this->scx = block[5] ;
  854.       this->scy = block[6] ;
  855.       }
  856.  
  857.    while (r.r[0] != 0)
  858.       {
  859.       scx = block[5] ;
  860.       scy = block[6] ;
  861.       gx0 = block[7] ;
  862.       gy0 = block[8] ;
  863.       gx1 = block[9] ;
  864.       gy1 = block[10] ;
  865.       minx = block[1] ;
  866.       maxy = block[4] ;
  867.       wx0 = gx0 + (scx - minx) ;
  868.       wy0 = gy0 + (scy - maxy) ;
  869.       wx1 = gx1 + (scx - minx) ;
  870.       wy1 = gy1 + (scy - maxy) ;
  871.  
  872.       for (object = objects ; object != NULL ; object = object->next)
  873.          object->redraw(wx0, wy0, wx1, wy1) ;
  874.       if ((e = _kernel_swi (Wimp_GetRectangle, &r, &r)) != NULL)
  875.          {
  876.          task->exit_critical() ;
  877.          throw (e) ;
  878.          }
  879.       }
  880.    task->exit_critical() ;
  881.    }
  882.  
  883. void Window::open(int x0, int y0, int x1, int y1, int scx, int scy, int behind)
  884.    {
  885.    do_open (x0, y0, x1, y1, scx, scy, behind) ;
  886.    }
  887.  
  888. void Window::close()
  889.    {
  890.    do_close() ;
  891.    }
  892.  
  893. void Window::drag (int x0, int y0, int x1, int y1, int id)
  894.    {
  895.    }
  896.  
  897.  
  898. void Window::pointer(int entering)
  899.    {
  900.    if (objects == NULL)                   // no objects?
  901.       return ;
  902.    if (entering)
  903.       {
  904.       if (tracker == NULL)
  905.          {
  906.          tracker = new MouseTracker (this) ;
  907.          tracker->start() ;
  908.          }
  909.       }
  910.    else
  911.       {
  912.       if (tracker != NULL)
  913.          {
  914.          delete tracker ;
  915.          tracker = NULL ;
  916.          }
  917.       }
  918.    }
  919.  
  920. Object *Window::find_object (int mx, int my)
  921.    {
  922.    Object *object ;
  923.    for (object = last_object ; object != NULL ; object = object->prev)
  924.       if (object->compare(mx, my))
  925.          return object ;
  926.    return NULL ;
  927.    }
  928.  
  929. Object *Window::find_object (char *name)
  930.    {
  931.    Object *object ;
  932.    for (object = last_object ; object != NULL ; object = object->prev)
  933.       if (strcmp (name, object->name) == 0)
  934.          return object ;
  935.    return NULL ;
  936.    }
  937.  
  938.  
  939. void Window::click(int mx, int my, int buttons, int icon)
  940.    {
  941.    }
  942.  
  943. void Window::key(int icon, int x, int y, int height, int index, int code)
  944.    {
  945.    }
  946.  
  947. void Window::scroll(int x0, int y0, int x1, int y1, int scx, int scy, int behind, int xdir, int ydir)
  948.    {
  949.    }
  950.  
  951. void Window::caret(int gaining, int icon, int x, int y, int height, int index)
  952.    {
  953.    }
  954.  
  955. //
  956. // display a menu on the screen due to the menu button being pressed over the window
  957. //
  958.  
  959. Menu *Window::display_menu(int x, int y, int button, int icon)
  960.    {
  961.    if (default_menu == NULL)
  962.       {
  963.       char *menu_name = get_menu(x, y, button, icon) ;
  964.       if (menu_name == NULL)
  965.          return NULL ;
  966.       Menu *m = task->find_menu (menu_name) ;
  967.       if (m != NULL)
  968.          {
  969.          m->open (x - 40, y) ;
  970.          return m ;
  971.          }
  972.       return NULL ;       // no menu
  973.       }
  974.    else
  975.       {
  976.       pre_menu (default_menu, x,  y,  button,  icon) ;
  977.       default_menu->open (x - 40, y) ;
  978.       return default_menu ;
  979.       }
  980.    }
  981.  
  982. //
  983. // give user a chance to change the menu before display
  984. //
  985.  
  986. void Window::pre_menu (Menu *m, int x, int y, int button, int icon)
  987.    {
  988.    }
  989.  
  990. //
  991. // this window doesn't have a default menu, ask the user to provide one
  992. //
  993.  
  994.  
  995. char *Window::get_menu (int x, int y, int button, int icon)
  996.    {
  997.    return NULL ;
  998.    }
  999.  
  1000. void Window::menu (MenuItem items[])
  1001.    {
  1002.    }
  1003.  
  1004.  
  1005. Icon *Window::find_icon (int icon)
  1006.    {
  1007.    Icon *ip ;
  1008.    for (ip = icons ; ip != NULL ; ip = ip->next)
  1009.       if (ip->compare(icon))
  1010.          break ;
  1011.    return ip ;
  1012.    }
  1013.  
  1014. Window *Window::find_window (int h)
  1015.    {
  1016.    Window *sub ;
  1017.    if (h == handle)
  1018.       return this ;
  1019.    for (Window *w = sub_windows ; w != NULL ; w = w->next)
  1020.       if ((sub = w->find_window(h)) != NULL)
  1021.          return sub ;
  1022.    return NULL ;
  1023.    }
  1024.  
  1025.  
  1026. void Window::mode_change()
  1027.    {
  1028.    Object *object ;
  1029.    for (object = objects ; object != NULL ; object = object->next)
  1030.       object->mode_change() ;
  1031.    }
  1032.  
  1033. char *Window::help (int mx, int my, int buttons, int icon)
  1034.    {
  1035.    return NULL ;
  1036.    }
  1037.  
  1038. //
  1039. // mouse tracker thread
  1040. //
  1041.  
  1042. MouseTracker::MouseTracker (Window *w)
  1043.    : Thread ("Tracker", 55)
  1044.  
  1045.    {
  1046.    window = w ;
  1047.    }
  1048.  
  1049. MouseTracker::~MouseTracker()
  1050.    {
  1051.    }
  1052.  
  1053.  
  1054. void MouseTracker::run()
  1055.    {
  1056.    _kernel_swi_regs r ;
  1057.    _kernel_oserror *e ;
  1058.    int block[5] ;
  1059.    Object *object = NULL ;                  // current object
  1060.    Object *o ;
  1061. //   Window *w = new Window (window->task, "counter") ;
  1062. //   Icon *ic = new Icon (w, 0) ;
  1063. //   w->do_open() ;
  1064.    for (;;)
  1065.       {
  1066.       r.r[1] = (int)block ;
  1067.       if ((e = _kernel_swi (Wimp_GetPointerInfo, &r, &r)) != NULL)    // get pointer position
  1068.          throw (e) ;
  1069.       o = window->find_object(block[0], block[1]) ;                // look for an object
  1070. //      ic->print ("%x",o) ;
  1071.       if (o != object)            // has object changed?
  1072.          {
  1073.      if (object != NULL)      // was there a previous object
  1074.         object->pointer(0) ;  // yes, leave
  1075.      object = o ;             // this is now current object
  1076.      if (o != NULL)          // any object now
  1077.            o->pointer (1) ;      // enter it
  1078.          }
  1079.       yield() ;                   // yield to next thread
  1080.       }
  1081.    }
  1082.  
  1083.