home *** CD-ROM | disk | FTP | other *** search
/ Really Useful CD 1 / ReallyUsefulCD1.iso / extras / utilities / _vmode / c / vmode
Encoding:
Text File  |  1992-02-23  |  21.3 KB  |  1,054 lines

  1. /* #define DEBUG */
  2.  
  3. /* $Id: c.vmode 1.3 92/02/25 11:45:32 bdb Exp $
  4.  *
  5.  * $Log:    c.vmode $
  6.  * Revision 1.3  92/02/25  11:45:32  bdb
  7.  * Changed newtasks behaviour to only trap on -trl ones,
  8.  * and no longer use weird patch. This supports a newtask
  9.  * command to replace taskwindow.
  10.  * 
  11.  * Revision 1.2  92/02/20  11:03:22  bdb
  12.  * Added cursor, passing on keys
  13.  * dbox_query replaces error box.
  14.  * 
  15.  * Revision 1.1  92/02/19  16:28:10  bdb
  16.  * Initial revision
  17.  * 
  18.  */
  19.  
  20. #define REVISION "$Revision: 1.3 $"
  21. #define VERSION ( REVISION " " __DATE__ " " __TIME__ + 11 )
  22.  
  23. #include "wimp.h"
  24. #include "wimpt.h"
  25. #include "win.h"
  26. #include "event.h"
  27. #include "res.h"
  28. #include "resspr.h"
  29. #include "menu.h"
  30. #include "template.h"
  31. #include "dbox.h"
  32. #include "dboxquery.h"
  33. #include "alarm.h"
  34. #include "baricon.h"
  35. #include "xfersend.h"
  36. #include "saveas.h"
  37. #include "werr.h"
  38. #include "flex.h"
  39. #include "visdelay.h"
  40. #include "akbd.h"
  41. #include "pointer.h"
  42. #include "bbc.h"
  43. #include "colourtran.h"
  44. #include "kernel.h"
  45. #include "swis.h"
  46. #include "swiv.h"
  47.  
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <stdarg.h>
  51. #include <signal.h>
  52.  
  53. #define min(x,y) ((x)<(y)?(x):(y))
  54. #define max(x,y) ((x)>(y)?(x):(y))
  55.  
  56.  
  57. enum themenu { MNULL, MKILL, MRECONNECT, MSUSPEND, MRESUME, MSAVE };
  58. #define themenuinit "Kill,Reconnect,Suspend,Resume,>Save"
  59.  
  60. enum state { TDEAD, TSUSPENDED, TRUNNING };
  61.  
  62. /* Container for info about a window */
  63. typedef struct win
  64. { wimp_w w;             /* window handle */
  65.   char title[256];      /* displayed title of window - indirecttext pts here */
  66.   struct win *next;
  67.   sprite_area *area;
  68.   int osx,osy;
  69.   int *save_area;
  70.   char *pixtrans;
  71.   wimp_t task;
  72.   int mode;
  73.   int l2bpp;
  74.   int xeig,yeig;
  75.   int changed;
  76.   enum state state;
  77.   int charx,chary;
  78.   int curx,cury;
  79. } win;
  80.  
  81. static os_error NoMem = { 0, "Out of Memory" };
  82.  
  83. static win *thewins = NULL;
  84. static int newtasks = 1; /* Catch new taskwindows */
  85.  
  86. static menu themenu;
  87. static menu barmenu=NULL;
  88. static wimp_i theicon;
  89.  
  90. static int wimpversion;
  91.  
  92. /* Saved win during drag or save/open message bounce */
  93. static win *savewin = NULL;
  94.  
  95. /* Prototypes */
  96.  
  97. #include "VMode.h"
  98.  
  99. int main
  100. ( int argc, char *argv[] )
  101. {
  102.   int i;
  103.   init();
  104.   for (i = 1; i<argc; i++)
  105.     launchone(argv[i],0);
  106.   for (;;)
  107.   { event_process();
  108.   }
  109.   return 0;
  110. }
  111.  
  112. void init
  113. ( void )
  114. {
  115.     wimpversion = wimpt_init("VMode");
  116. #ifdef DEBUG
  117.     signal(SIGABRT, SIG_DFL);
  118.     signal(SIGFPE, SIG_DFL);
  119.     signal(SIGILL, SIG_DFL);
  120.     signal(SIGSEGV, SIG_DFL);
  121.     signal(SIGTERM, SIG_DFL);
  122. #endif
  123.     res_init("VMode");
  124.     resspr_init();
  125.     template_init();
  126.     dbox_init();
  127.     alarm_init();
  128.     visdelay_init();
  129.     flex_init();
  130.     win_add_unknown_event_processor( unknownevent, NULL );
  131.     theicon = baricon( "!VMode", 1, barclick );
  132.     event_attachmenumaker( win_ICONBAR, barmenumaker, barmenuproc, NULL );
  133.     themenu = menu_new( "VMode", themenuinit );
  134.     newtasks = atoi(getenv("VMode$NewTasks"));
  135. }
  136.  
  137. sprite_id *SprPtr
  138. (sprite_header *s)
  139. {
  140.         static sprite_id id;
  141.         id.tag = sprite_id_addr;
  142.         id.s.addr = s;
  143.         return &id;
  144. }
  145.  
  146. sprite_id *SprNam
  147. (char *s)
  148. {
  149.         static sprite_id id;
  150.         id.tag = sprite_id_name;
  151.         id.s.name = s;
  152.         return &id;
  153. }
  154.  
  155. menu menumaker
  156. ( void *h )
  157. { win *w = h;
  158.   menu_setflags( themenu, MKILL, 0, (w->state==TDEAD) );
  159.   menu_setflags( themenu, MRECONNECT, 0, (w->state!=TDEAD) );
  160.   menu_setflags( themenu, MSUSPEND, 0, (w->state!=TRUNNING) );
  161.   menu_setflags( themenu, MRESUME, 0, (w->state!=TSUSPENDED) );
  162.   return themenu;
  163. }
  164.  
  165. void menuproc
  166. ( void *h, char *hit )
  167. { wimp_mousestr m;
  168.   wimp_msgstr msg;
  169.   win *w = h;
  170.   wimpt_noerr( wimp_get_point_info( &m ) );
  171.   switch ( hit[0] )
  172.   { case MKILL:
  173.       msg.hdr.action = 0x808c4; /* TaskWindow_Morite */
  174.       w->state = TDEAD;
  175.       goto sendit;
  176.     case MRECONNECT:
  177.       wimp_starttask(w->title);
  178.       w->state = TDEAD;
  179.       break;
  180.     case MSUSPEND:
  181.       msg.hdr.action = 0x808c6; /* TaskWindow_Suspend */
  182.       w->state = TSUSPENDED;
  183.       goto sendit;
  184.     case MRESUME:
  185.       msg.hdr.action = 0x808c7; /* TaskWindow_Resume */
  186.       w->state = TRUNNING;
  187. sendit:
  188.       msg.hdr.your_ref = 0;
  189.       msg.hdr.size = 20;
  190.       wimpt_noerr( wimp_sendmessage( wimp_ESEND, &msg, w->task ) );
  191.       break;
  192.     case MSAVE:
  193.       saveas( 0xff9, "screendump", 1, saveproc, 0, 0, w );
  194.       break;
  195.   }
  196. }
  197.  
  198. BOOL saveproc
  199. ( char *filename, void *h )
  200. { win *w = h;
  201.   BOOL b;
  202.   b = !wimpt_complain(sprite_area_save(w->area,filename));
  203.   if ( b && xfersend_file_is_safe() )
  204.     h = NULL; /* maybe fiddle title */
  205.   return b;
  206. }
  207.  
  208. void winevent
  209. ( wimp_eventstr *e, void *h )
  210. { BOOL more;
  211.   win *w = h;
  212.   wimp_redrawstr r;
  213.   switch ( e->e )
  214.   { case wimp_EREDRAW:
  215.       if (wimpt_checkmode())
  216.         coltable(w);
  217.       r.w = e->data.o.w;
  218.       wimpt_noerr(wimp_redraw_wind(&r,&more));
  219.       while (more)
  220.       { int a,b;
  221.         wimpt_noerr(sprite_put_scaled( w->area, SprNam("screen"), 0,
  222.                  r.box.x0-r.scx, r.box.y1-r.scy-w->osy, NULL, w->pixtrans));
  223.         bbc_gcol(4,0);
  224.         a = w->curx*w->charx+r.box.x0-r.scx;
  225.         b = -(w->cury+1)*w->chary+r.box.y1-r.scy;
  226.         bbc_rectanglefill(a,b,w->charx,w->chary-1);
  227.         wimpt_noerr(wimp_get_rectangle(&r,&more));
  228.       }
  229.       break;
  230.     case wimp_EOPEN:
  231.       wimp_open_wind( &e->data.o );
  232.       break;
  233.     case wimp_ECLOSE:
  234.       if (w->state==TDEAD || confirm("Task active. Kill and close?"))
  235.         freewin( w );
  236.       break;
  237.     case wimp_EBUT:
  238.       {
  239.         switch ( e->data.but.m.bbits )
  240.         { case wimp_BCLICKLEFT:
  241.           case wimp_BCLICKRIGHT:
  242.           case wimp_BDRAGLEFT:
  243.           case wimp_BDRAGRIGHT:
  244.           case wimp_BRIGHT:
  245.           case wimp_BLEFT:
  246.             grabcaret(w);
  247.             break;
  248.         }
  249.         break;
  250.       }
  251.     case wimp_EKEY:
  252.       { int code = e->data.key.chcode;
  253.         if (code>0xFF)
  254.           wimp_processkey(code);
  255.         else
  256.         { e->data.msg.hdr.action = 0x808c0; /* TaskWindow_Input */
  257.           e->data.msg.hdr.your_ref = 0;
  258.           e->data.msg.hdr.size = 28;
  259.           e->data.msg.data.words[0]=1;
  260.           e->data.msg.data.words[1]=code;
  261.           wimpt_noerr( wimp_sendmessage( wimp_ESEND, &e->data.msg, w->task ) );
  262.       } }
  263.       break;
  264.     case wimp_ESEND: case wimp_ESENDWANTACK:
  265.       switch ( e->data.msg.hdr.action )
  266.       { case wimp_MCLOSEDOWN:
  267.           while (thewins)
  268.             freewin(thewins);
  269.           exit(0);
  270.           break;
  271.       }
  272.       break;
  273.   }
  274. }
  275.  
  276. BOOL oktoquit
  277. ( void )
  278. {
  279.   win *w;
  280.   for ( w=thewins; w ; w=w->next)
  281.     if (w->state!=TDEAD)
  282.       break;
  283.   if ( w )
  284.     if ( confirm( "There are still tasks running under !VMode. Really quit?" ) )
  285.       w=NULL;
  286.   return w==NULL;
  287. }
  288.  
  289. BOOL unknownevent
  290. ( wimp_eventstr *e, void *h )
  291. { win *w=h;
  292.   sprite_state s, s2;
  293.   wimp_redrawstr r;
  294.   int *box;
  295.   int s1;
  296.   switch ( e->e )
  297.   { case wimp_ENULL:
  298.       s1 = 0;
  299.       for (w = thewins; w; w = w->next)
  300.       { if (w->changed)
  301.         { int cx,cy;
  302.           wimpt_noerr(sprite_outputtosprite(w->area, SprNam("screen"), w->save_area, s1?&s2:&s));
  303.           s1 = 1;
  304.           swix(OS_ChangedBox,IN(R0)|OUT(R1),-1,&box);
  305.           r.w = w->w;
  306.           r.box.x0 = box[1]<<w->xeig;
  307.           r.box.y0 = (box[2]<<w->yeig)-w->osy;
  308.           r.box.x1 = (box[3]+1<<w->xeig);
  309.           r.box.y1 = (box[4]+1<<w->yeig)-w->osy;
  310.           swix(OS_ChangedBox,IN(R0),2);
  311.           if (r.box.x1>r.box.x0 && r.box.y1>r.box.y0)
  312.             wimpt_noerr(wimp_force_redraw(&r));
  313.           cx = bbc_pos();
  314.           cy = bbc_vpos();
  315.           if ( cx!=w->curx || cy!=w->cury )
  316.           { r.w = w->w;
  317.             r.box.x0 = w->curx*w->charx;
  318.             r.box.y1 = -w->cury*w->chary;
  319.             r.box.x1 = r.box.x0+w->charx;
  320.             r.box.y0 = r.box.y1-w->chary;
  321.             wimpt_noerr(wimp_force_redraw(&r));
  322.             w->curx = cx;
  323.             w->cury = cy;
  324.             r.w = w->w;
  325.             r.box.x0 = w->curx*w->charx;
  326.             r.box.y1 = -w->cury*w->chary;
  327.             r.box.x1 = r.box.x0+w->charx;
  328.             r.box.y0 = r.box.y1-w->chary;
  329.             wimpt_noerr(wimp_force_redraw(&r));
  330.           }
  331.           w->changed = 0;
  332.       } }
  333.       if (s1)
  334.         wimpt_noerr(sprite_restorestate(s));
  335.       break;
  336.     case wimp_ESEND: case wimp_ESENDWANTACK:
  337.       w = savewin;
  338.       switch ( e->data.msg.hdr.action )
  339.       { case wimp_MPREQUIT:
  340.           if ( !oktoquit() )
  341.           { ack( &e->data.msg );
  342.             return TRUE;
  343.           }
  344.           break;
  345.         case wimp_SAVEDESK:
  346.           { int fh = e->data.msg.data.savedesk.filehandle;
  347.             rofprintf( fh, "Run %s\n", getenv("VMode$Dir") );
  348.           }
  349.           break;
  350.         case 0x808c5: /* TaskWindow_NewTask */
  351.           if (newtasks && strstr(&e->data.msg.data.chars[0],"-ctrl"))
  352.           {
  353.             ack(&e->data.msg);
  354. /* the weird flag is now set to 0, since the above message cannot have really
  355.  * come from taskwindow as its too broken to pass -ctrl through, and so we
  356.  * don't have to worry about its other bugs
  357.  */
  358.             launchone(&e->data.msg.data.chars[0],0);
  359.           }
  360.           break;
  361.         case 0x808c3: /* TaskWindow_Morio */
  362.           for (w = thewins; w; w = w->next )
  363.             if (w->task==e->data.msg.hdr.task)
  364.               w->state = TDEAD;
  365.           break;
  366.         case 0x808c2: /* TaskWindow_Ego */
  367.           w = (win *)e->data.msg.data.words[0];
  368.           w->task = e->data.msg.hdr.task;
  369.           w->state = TRUNNING;
  370.           break;
  371.         case 0x808c1: /* TaskWindow_Output */
  372.           for ( w=thewins ; w ; w=w->next )
  373.             if (w->task==e->data.msg.hdr.task)
  374.               break;
  375.           if (w)
  376.             scribble( w, (char *)&e->data.msg.data.words[1], e->data.msg.data.words[0] );
  377.           break;
  378.       }
  379.       break;
  380.     case wimp_EACK:
  381.       break;
  382.   }
  383.   return FALSE;
  384. }
  385.  
  386. void barclick
  387. ( wimp_i i )
  388. { i = i;
  389.   launchone("taskwindow -ctrl",0);
  390. }
  391.  
  392. void launchone
  393. ( char *cmd, int weird )
  394. { wimp_wind *t;
  395.   wimp_wstate s;
  396.   win *w=claim(sizeof(win));
  397. /* NB taskwindow seems only to recognise a reply to a request for a server if
  398.  * hex no.s with no &'s or flag names are used... odd!
  399.  */
  400.   if (weird)
  401.     sprintf( w->title,"%s %08x  %08x ", cmd, wimpt_task(), (int)w );
  402.   else
  403.     sprintf( w->title,"%s -task &%08x -txt &%08x ", cmd, wimpt_task(), (int)w );
  404.   w->next = thewins;
  405.   thewins = w;
  406.   t = template_syshandle( "window" );
  407.   t->title.indirecttext.buffer = w->title;
  408.   t->title.indirecttext.bufflen = 256;
  409.   wimpt_noerr( wimp_create_wind( t, &w->w ) );
  410.   win_register_event_handler( w->w, winevent, (void *)w );
  411.   event_attachmenumaker( w->w, menumaker, menuproc, (void *)w );
  412.   w->area = NULL;
  413.   w->pixtrans = NULL;
  414.   w->save_area = NULL;
  415.   if (!modeclear(w,0))
  416.   {
  417.     wimpt_noerr( wimp_get_wind_state( w->w, &s ) );
  418.     wimpt_noerr( wimp_open_wind( &s.o ) );
  419.     event_setmask( 0 );
  420.     wimp_starttask(w->title);
  421.     w->state = TDEAD;
  422.     grabcaret(w);
  423.   }
  424.   else
  425.     freewin(w);
  426. }
  427.  
  428. void grabcaret
  429. ( win *w )
  430. { wimp_caretstr c;
  431.   c.w = w->w;
  432.   c.i = -1;
  433.   c.x = 100;
  434.   c.y = -100;
  435.   c.height = 0|(1<<25); /* invisible */
  436.   c.index = 0;
  437.   wimpt_noerr(wimp_set_caret_pos(&c));
  438. }
  439.  
  440. static int pal2[4]=
  441. {
  442. 0x0,
  443. 0xF0F0F007,
  444. };
  445. static int pal4[8]=
  446. {
  447. 0x0,
  448. 0xF001,
  449. 0xF0F003,
  450. 0xF0F0F007,
  451. };
  452. static int pal16[32]=
  453. {
  454. 0x0,
  455. 0xF001,
  456. 0xF00002,
  457. 0xF0F003,
  458. 0xF0000004,
  459. 0xF000F005,
  460. 0xF0F00006,
  461. 0xF0F0F007,
  462. 0x8,
  463. 0xF009,
  464. 0xF0000A,
  465. 0xF0F00B,
  466. 0xF000000C,
  467. 0xF000F00D,
  468. 0xF0F0000E,
  469. 0xF0F0F00F,
  470. };
  471. static int pal256[512]=
  472. {
  473. 0x10,
  474. 0x10101010,
  475. 0x20202010,
  476. 0x30303010,
  477. 0x4010,
  478. 0x10105010,
  479. 0x20206010,
  480. 0x30307010,
  481. 0x40000010,
  482. 0x50101010,
  483. 0x60202010,
  484. 0x70303010,
  485. 0x40004010,
  486. 0x50105010,
  487. 0x60206010,
  488. 0x70307010,
  489. 0x8010,
  490. 0x10109010,
  491. 0x2020A010,
  492. 0x3030B010,
  493. 0xC010,
  494. 0x1010D010,
  495. 0x2020E010,
  496. 0x3030F010,
  497. 0x40008010,
  498. 0x50109010,
  499. 0x6020A010,
  500. 0x7030B010,
  501. 0x4000C010,
  502. 0x5010D010,
  503. 0x6020E010,
  504. 0x7030F010,
  505. 0x400010,
  506. 0x10501010,
  507. 0x20602010,
  508. 0x30703010,
  509. 0x404010,
  510. 0x10505010,
  511. 0x20606010,
  512. 0x30707010,
  513. 0x40400010,
  514. 0x50501010,
  515. 0x60602010,
  516. 0x70703010,
  517. 0x40404010,
  518. 0x50505010,
  519. 0x60606010,
  520. 0x70707010,
  521. 0x408010,
  522. 0x10509010,
  523. 0x2060A010,
  524. 0x3070B010,
  525. 0x40C010,
  526. 0x1050D010,
  527. 0x2060E010,
  528. 0x3070F010,
  529. 0x40408010,
  530. 0x50509010,
  531. 0x6060A010,
  532. 0x7070B010,
  533. 0x4040C010,
  534. 0x5050D010,
  535. 0x6060E010,
  536. 0x7070F010,
  537. 0x800010,
  538. 0x10901010,
  539. 0x20A02010,
  540. 0x30B03010,
  541. 0x804010,
  542. 0x10905010,
  543. 0x20A06010,
  544. 0x30B07010,
  545. 0x40800010,
  546. 0x50901010,
  547. 0x60A02010,
  548. 0x70B03010,
  549. 0x40804010,
  550. 0x50905010,
  551. 0x60A06010,
  552. 0x70B07010,
  553. 0x808010,
  554. 0x10909010,
  555. 0x20A0A010,
  556. 0x30B0B010,
  557. 0x80C010,
  558. 0x1090D010,
  559. 0x20A0E010,
  560. 0x30B0F010,
  561. 0x40808010,
  562. 0x50909010,
  563. 0x60A0A010,
  564. 0x70B0B010,
  565. 0x4080C010,
  566. 0x5090D010,
  567. 0x60A0E010,
  568. 0x70B0F010,
  569. 0xC00010,
  570. 0x10D01010,
  571. 0x20E02010,
  572. 0x30F03010,
  573. 0xC04010,
  574. 0x10D05010,
  575. 0x20E06010,
  576. 0x30F07010,
  577. 0x40C00010,
  578. 0x50D01010,
  579. 0x60E02010,
  580. 0x70F03010,
  581. 0x40C04010,
  582. 0x50D05010,
  583. 0x60E06010,
  584. 0x70F07010,
  585. 0xC08010,
  586. 0x10D09010,
  587. 0x20E0A010,
  588. 0x30F0B010,
  589. 0xC0C010,
  590. 0x10D0D010,
  591. 0x20E0E010,
  592. 0x30F0F010,
  593. 0x40C08010,
  594. 0x50D09010,
  595. 0x60E0A010,
  596. 0x70F0B010,
  597. 0x40C0C010,
  598. 0x50D0D010,
  599. 0x60E0E010,
  600. 0x70F0F010,
  601. 0x80000010,
  602. 0x90101010,
  603. 0xA0202010,
  604. 0xB0303010,
  605. 0x80004010,
  606. 0x90105010,
  607. 0xA0206010,
  608. 0xB0307010,
  609. 0xC0000010,
  610. 0xD0101010,
  611. 0xE0202010,
  612. 0xF0303010,
  613. 0xC0004010,
  614. 0xD0105010,
  615. 0xE0206010,
  616. 0xF0307010,
  617. 0x80008010,
  618. 0x90109010,
  619. 0xA020A010,
  620. 0xB030B010,
  621. 0x8000C010,
  622. 0x9010D010,
  623. 0xA020E010,
  624. 0xB030F010,
  625. 0xC0008010,
  626. 0xD0109010,
  627. 0xE020A010,
  628. 0xF030B010,
  629. 0xC000C010,
  630. 0xD010D010,
  631. 0xE020E010,
  632. 0xF030F010,
  633. 0x80400010,
  634. 0x90501010,
  635. 0xA0602010,
  636. 0xB0703010,
  637. 0x80404010,
  638. 0x90505010,
  639. 0xA0606010,
  640. 0xB0707010,
  641. 0xC0400010,
  642. 0xD0501010,
  643. 0xE0602010,
  644. 0xF0703010,
  645. 0xC0404010,
  646. 0xD0505010,
  647. 0xE0606010,
  648. 0xF0707010,
  649. 0x80408010,
  650. 0x90509010,
  651. 0xA060A010,
  652. 0xB070B010,
  653. 0x8040C010,
  654. 0x9050D010,
  655. 0xA060E010,
  656. 0xB070F010,
  657. 0xC0408010,
  658. 0xD0509010,
  659. 0xE060A010,
  660. 0xF070B010,
  661. 0xC040C010,
  662. 0xD050D010,
  663. 0xE060E010,
  664. 0xF070F010,
  665. 0x80800010,
  666. 0x90901010,
  667. 0xA0A02010,
  668. 0xB0B03010,
  669. 0x80804010,
  670. 0x90905010,
  671. 0xA0A06010,
  672. 0xB0B07010,
  673. 0xC0800010,
  674. 0xD0901010,
  675. 0xE0A02010,
  676. 0xF0B03010,
  677. 0xC0804010,
  678. 0xD0905010,
  679. 0xE0A06010,
  680. 0xF0B07010,
  681. 0x80808010,
  682. 0x90909010,
  683. 0xA0A0A010,
  684. 0xB0B0B010,
  685. 0x8080C010,
  686. 0x9090D010,
  687. 0xA0A0E010,
  688. 0xB0B0F010,
  689. 0xC0808010,
  690. 0xD0909010,
  691. 0xE0A0A010,
  692. 0xF0B0B010,
  693. 0xC080C010,
  694. 0xD090D010,
  695. 0xE0A0E010,
  696. 0xF0B0F010,
  697. 0x80C00010,
  698. 0x90D01010,
  699. 0xA0E02010,
  700. 0xB0F03010,
  701. 0x80C04010,
  702. 0x90D05010,
  703. 0xA0E06010,
  704. 0xB0F07010,
  705. 0xC0C00010,
  706. 0xD0D01010,
  707. 0xE0E02010,
  708. 0xF0F03010,
  709. 0xC0C04010,
  710. 0xD0D05010,
  711. 0xE0E06010,
  712. 0xF0F07010,
  713. 0x80C08010,
  714. 0x90D09010,
  715. 0xA0E0A010,
  716. 0xB0F0B010,
  717. 0x80C0C010,
  718. 0x90D0D010,
  719. 0xA0E0E010,
  720. 0xB0F0F010,
  721. 0xC0C08010,
  722. 0xD0D09010,
  723. 0xE0E0A010,
  724. 0xF0F0B010,
  725. 0xC0C0C010,
  726. 0xD0D0D010,
  727. 0xE0E0E010,
  728. 0xF0F0F010,
  729. };
  730. static int *bpptab[4]={pal2,pal4,pal16,pal256};
  731.  
  732. void modefree
  733. ( win *w )
  734. {
  735.   if (w->area)
  736.     flex_free((flex_ptr)&w->area);
  737.   if (w->save_area)
  738.     free(w->save_area);
  739.   w->save_area=NULL;
  740.   if (w->pixtrans)
  741.     free(w->pixtrans);
  742.   w->pixtrans=NULL;
  743. }
  744.  
  745. os_error *modeclear
  746. ( win*w, int mode )
  747. {
  748.   int size,bpp,x,y;
  749.   sprite_state s;
  750.   wimp_redrawstr r;
  751.   wimp_wstate state;
  752.   os_error *err;
  753.   w->mode = mode;
  754.   x = bbc_modevar(mode,bbc_XWindLimit)+1;
  755.   y = bbc_modevar(mode,bbc_YWindLimit)+1;
  756.   w->l2bpp = bbc_modevar(mode,bbc_Log2BPP);
  757.   bpp = 1 << w->l2bpp;
  758.   w->osx = x << (w->xeig=bbc_modevar(mode,bbc_XEigFactor));
  759.   w->osy = y << (w->yeig=bbc_modevar(mode,bbc_YEigFactor));
  760.   w->charx = 8 << w->xeig;
  761.   w->chary = (bbc_modevar(mode,bbc_ModeFlags)&(1<<5)?16:8) << w->yeig;
  762.   size = sizeof(sprite_area)+sizeof(sprite_header)+x*y*bpp/8;
  763.   if (!flex_alloc((flex_ptr)&w->area, size))
  764.     return wimpt_complain(&NoMem);
  765.   sprite_area_initialise(w->area, size);
  766.   err=wimpt_complain(sprite_create(w->area, "screen", sprite_nopalette, x, y, mode));
  767.   if (err) return err;    
  768.   wimpt_noerr(sprite_sizeof_spritecontext(w->area, SprNam("screen"), &size));
  769.   w->save_area = claim(size);
  770.   w->save_area[0]=0;
  771.   w->pixtrans = claim(1<<bpp);
  772.   if (!w->save_area || !w->pixtrans)
  773.     return wimpt_complain(&NoMem);
  774.   wimpt_noerr(sprite_outputtosprite(w->area,  SprNam("screen"), w->save_area, &s));
  775.   swix(OS_ChangedBox,IN(R0),1);
  776.   swix(OS_ChangedBox,IN(R0),2);
  777.   wimpt_noerr(sprite_restorestate(s));
  778.   coltable(w);
  779.   r.w = w->w;
  780.   r.box.x0 = 0; r.box.x1 = w->osx; r.box.y0 = -w->osy; r.box.y1 = 0;
  781.   wimpt_noerr( wimp_get_wind_state( w->w, &state ) );
  782.   if (state.o.box.x1 > state.o.box.x0+w->osx)
  783.       state.o.box.x1 = state.o.box.x0+w->osx;
  784.   if (state.o.box.y0 < state.o.box.y1-w->osy)
  785.       state.o.box.y0 = state.o.box.y1-w->osy;
  786.   if (state.o.x < w->osx - (state.o.box.x1 - state.o.box.x0))
  787.       state.o.x = w->osx - (state.o.box.x1 - state.o.box.x0);
  788.   if (state.o.y < (state.o.box.y1 - state.o.box.y0) - w->osy)
  789.       state.o.y = (state.o.box.y1 - state.o.box.y0) - w->osy;
  790.   wimpt_noerr(wimp_open_wind(&state.o));
  791.   wimpt_noerr(wimp_set_extent(&r));
  792.   wimpt_noerr(wimp_force_redraw(&r));
  793.   return NULL;
  794. }
  795.  
  796. void coltable
  797. ( win *w )
  798. {
  799.   wimpt_noerr(colourtran_select_table(w->mode,(wimp_paletteword *)bpptab[w->l2bpp],-1,(wimp_paletteword *)-1,w->pixtrans));
  800. }
  801.  
  802. void scribble
  803. ( win *w, char *data, int size )
  804. {
  805.   sprite_state s;
  806.   char *p;
  807.   int q;
  808.   wimpt_noerr(sprite_outputtosprite(w->area,  SprNam("screen"), w->save_area, &s));
  809.   while (size && (p = memchr( data, 22, size ))!=NULL)
  810.   { if (p-data)
  811.       swix( OS_WriteN, IN(R0|R1), data, p-data );
  812.     size -= p-data;
  813.     data = p;
  814.     swix(OS_Byte,IN(R0|R1|R2)|OUT(R1),218,0,255,&q);
  815.     if (!q && size>=2 )
  816.     {
  817.       wimpt_noerr(sprite_restorestate(s));
  818.       modefree(w);
  819.       if (modeclear(w,data[1]))
  820.       { freewin(w);
  821.         return;
  822.       }
  823.       size-=2;
  824.       data+=2;
  825.       wimpt_noerr(sprite_outputtosprite(w->area,  SprNam("screen"), w->save_area, &s));
  826.     }
  827.     else
  828.     { swix(OS_WriteC,IN(R0),*data++);
  829.       size--;
  830.     }
  831.   }
  832.   if (size)
  833.     swix(OS_WriteN, IN(R0|R1), data, size);
  834.   w->changed = 1;
  835.   wimpt_noerr(sprite_restorestate(s));
  836. }
  837.  
  838. menu barmenumaker
  839. ( void *h )
  840. {
  841.   h=h;
  842.   if ( !event_is_menu_being_recreated() )
  843.   { if ( barmenu )
  844.       menu_dispose( &barmenu, 0 );
  845.     barmenu = menu_new( "VMode", ">Info,NewTasks,Quit" );
  846.     menu_setflags( barmenu, 2, newtasks, 0 );
  847.   }
  848.   return barmenu;
  849. }
  850.  
  851. void barmenuproc
  852. ( void *h, char *hit )
  853. {
  854.   h=h;
  855.   switch (hit[0])
  856.   { case 1:
  857.       infobox();
  858.       break;
  859.     case 2:
  860.       newtasks = ! newtasks;
  861.       break;
  862.     case 3:
  863.       if ( oktoquit() )
  864.       { while (thewins)
  865.           freewin(thewins);
  866.         exit(0);
  867.       }
  868.       break;
  869.   }
  870. }
  871.  
  872. /*
  873.  * Window manipulation
  874.  */
  875.  
  876. void newtitle
  877. ( win *w, char *n )
  878. { wimp_redrawstr r;
  879.   wimp_wstate s;
  880.   strcpy( w->title, n );
  881.   r.w = w->w;
  882.   wimpt_noerr( wimp_getwindowoutline( &r ) );
  883.   wimpt_noerr( wimp_get_wind_state( w->w, &s ) );
  884.   r.w = -1;
  885.   r.box.y0 = s.o.box.y1;
  886.   wimpt_noerr( wimp_force_redraw( &r ) );
  887. }
  888.  
  889. void behind
  890. ( win *w, int where )
  891. { wimp_wstate s;  
  892.   wimpt_noerr( wimp_get_wind_state( w->w, &s ) );
  893.   s.o.behind = where;
  894.   wimpt_noerr( wimp_open_wind( &s.o ) );
  895. }
  896.  
  897. void freewin
  898. ( win *w )
  899. {
  900.   win **w1;
  901.   if ( w->w )
  902.   { win_register_event_handler( w->w, 0, 0 );
  903.     alarm_removeall( (void *)w );
  904.     wimpt_noerr(wimp_delete_wind(w->w));
  905.   }
  906.   for ( w1=&thewins; *w1!=w; w1=&(*w1)->next )
  907.     if ( !*w1 )
  908.       werr( 1, "Chain of windows broken" );
  909.   if (w->state!=TDEAD)
  910.   { wimp_msgstr msg;
  911.     msg.hdr.action = 0x808c4; /* TaskWindow_Morite */
  912.     msg.hdr.your_ref = 0;
  913.     msg.hdr.size = 20;
  914.     wimpt_noerr( wimp_sendmessage( wimp_ESEND, &msg, w->task ) );
  915.   }
  916.   *w1 = w->next;
  917.   modefree(w);
  918.   free(w);
  919. }
  920.  
  921. /*
  922.  * Wimp utility
  923.  */
  924.  
  925. int confirm
  926. ( char *s )
  927. { return dboxquery(s)==dboxquery_YES;
  928. }
  929.  
  930. void infobox
  931. ( void )
  932. { dbox d;
  933.   d = dbox_new("info");
  934.   dbox_setfield(d, 3, VERSION );
  935.   dbox_show(d);
  936.   dbox_fillin(d);
  937.   dbox_dispose(&d);
  938. }
  939.  
  940. /*
  941.  * Safe memory allocation
  942.  */
  943.  
  944. void *claim
  945. ( int size )
  946. { void *p;
  947.   p = malloc( size );
  948.   if ( !p )
  949.     werr( 1, "out of memory" );
  950.   return p;
  951. }
  952.  
  953. void *reclaim
  954. ( void *q, int size )
  955. { void *p;
  956.   p = realloc( q, size );
  957.   if ( !p )
  958.     werr( 1, "out of memory" );
  959.   return p;
  960. }
  961.  
  962. /*
  963.  * Stuff to deal with sending Wimp messages
  964.  */
  965.  
  966. void reply
  967. ( wimp_msgstr* msg, int action )
  968. {
  969.   msg->hdr.your_ref = msg->hdr.my_ref;
  970.   msg->hdr.size = 44 + ( ( strlen( msg->data.datasaveok.name ) + 4 ) & -4 );
  971.   msg->hdr.action = action;
  972.   wimpt_noerr( wimp_sendmessage( wimp_ESEND, msg, msg->hdr.task ) );
  973. }
  974.  
  975. void replywantack
  976. ( wimp_msgstr* msg, int action )
  977. {
  978.   msg->hdr.your_ref = msg->hdr.my_ref;
  979.   msg->hdr.size = 44 + ( ( strlen( msg->data.datasaveok.name ) + 4 ) & -4 );
  980.   msg->hdr.action = action;
  981.   wimpt_noerr( wimp_sendmessage( wimp_ESENDWANTACK, msg, msg->hdr.task ) );
  982. }
  983.  
  984. void send
  985. ( wimp_msgstr* msg, int action, wimp_w w, wimp_i i )
  986. {
  987.   msg->hdr.size = 44 + ( ( strlen( msg->data.datasaveok.name ) + 4 ) & -4 );
  988.   msg->hdr.action = action;
  989.   wimpt_noerr( wimp_sendwmessage( wimp_ESEND, msg, w, i ) );
  990. }
  991.  
  992. void sendwantack
  993. ( wimp_msgstr* msg, int action, wimp_w w, wimp_i i )
  994. {
  995.   msg->hdr.size = 44 + ( ( strlen( msg->data.datasaveok.name ) + 4 ) & -4 );
  996.   msg->hdr.action = action;
  997.   wimpt_noerr( wimp_sendwmessage( wimp_ESENDWANTACK, msg, w, i ) );
  998. }
  999.  
  1000. void ack
  1001. ( wimp_msgstr* msg )
  1002. {
  1003.   msg->hdr.your_ref = msg->hdr.my_ref;
  1004.   wimpt_noerr( wimp_sendmessage( wimp_ESEND, msg, msg->hdr.task ) );
  1005. }
  1006.  
  1007. void rofprintf
  1008. ( int fh, char *fmt, ... )
  1009. { char buf[256];
  1010.   va_list arg;
  1011.   _kernel_osgbpb_block b;
  1012.   va_start( arg, fmt );
  1013.   vsprintf( buf, fmt, arg );
  1014.   va_end( arg );
  1015.   b.dataptr = buf;
  1016.   b.nbytes = strlen( buf );
  1017.   if (_kernel_osgbpb( 2, fh, &b )==_kernel_ERROR)
  1018.     wimpt_complain( (os_error *)_kernel_last_oserror() );
  1019. }
  1020.  
  1021. void strins
  1022. ( char *d, char *s )
  1023. /* Insert string s at the beginning of string d */
  1024. {
  1025.   int l=strlen(s);
  1026.   int m=strlen(d);
  1027.   memmove(&d[l],d,m+1);
  1028.   memmove(d,s,l);
  1029. }
  1030.  
  1031. char *strdup
  1032. ( char *d )
  1033. {
  1034.   int m=strlen(d);
  1035.   char *p = claim(m+1);
  1036.   if (p)
  1037.     strcpy( p, d );
  1038.   return p;
  1039. }
  1040.  
  1041. char *strjoin
  1042. ( char *s, char *t )
  1043. {
  1044.   int m=strlen(s);
  1045.   int n=strlen(t);
  1046.   char *p = claim( m+n+1 );
  1047.   if (p)
  1048.   { strcpy( p, s );
  1049.     strcpy( p+m, t );
  1050.   }
  1051.   return p;
  1052. }
  1053.  
  1054.