home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 144.lha / Leach_v1.3 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-21  |  15.1 KB  |  502 lines

  1. /*****************************************************************************
  2.  *
  3.  *                                LEACH Ver 1.3
  4.  *
  5.  * This is an auxilery program to Digi-View 2.0. Leach analyses Digi-View's
  6.  * Intuition structures and worms its way in between Intuition and the Host.
  7.  * The purpose of Leach is to provide a "ruler" line that appears on the Host's
  8.  * display screen. See leach.doc for details.
  9.  *
  10.  *                THIS FILE USES 4 COLUMN TAB STOPS AND 80 COLUMNS
  11.  *
  12.  *****************************************************************************/
  13.  
  14.  
  15. #include    <functions.h>
  16. #include    <exec/ports.h>
  17. #include    <exec/types.h>
  18. #include     <exec/nodes.h>
  19. #include    <exec/libraries.h>
  20. #include    <exec/tasks.h>
  21. #include    <graphics/gfx.h>
  22. #include    <graphics/rastport.h>
  23. #include    <graphics/text.h>
  24. #include    <intuition/intuitionbase.h>
  25. #include     <stdio.h>
  26.  
  27.  
  28. struct Library *GfxBase            = NULL;
  29. struct Library *IntuitionBase    = NULL;
  30.  
  31.  
  32. /***********************  SCREEN AND WINDOW STUFF  **************************/
  33.  
  34. /*--------------------------------------------------------------------------*
  35.  * Leach uses its screen just for the status display window. It displays the
  36.  * ruler on the Host's screen. globals.h declares most of the Host variables.
  37.  *--------------------------------------------------------------------------*/
  38.  
  39. #define SHOWGAD swind_gad[0]
  40. #define MOVEGAD swind_gad[1]
  41.  
  42. #define GLOBAL
  43. #include "globals.h"
  44.  
  45. /************  LEACH'S STATUS DISPLAY NEWSCREEN STRUCTURE  ******************/
  46.  
  47. static UBYTE ScrTitle[] = " Leach Ver 1.3 ";
  48.  
  49. struct NewScreen LeachScreen =
  50. {
  51. 0, 178,            /* LeftEdge, TopEdge                */
  52. 640, 22, 2,        /* Width, Height, Depth                */
  53. 0, 1,            /* Detail & Block pens.                */
  54. HIRES,            /* View Modes                        */
  55. CUSTOMSCREEN,    /* Type                                */
  56. NULL,            /* Text attributes                    */
  57. ScrTitle,
  58. NULL,            /* Pointer to screen gadget list.    */
  59. NULL            /* Pointer to custom bitmap.        */
  60. };
  61.  
  62.  
  63. /******  The rest of this stuff is for Leach's status display window.  ******/
  64.  
  65. extern struct Gadget    swind_gad[];
  66.  
  67. static UBYTE StatWindTitle[] = 
  68. " Digi-Leach V1.3                  Copyright (c) 1988 by  Drew Lucy ";
  69.  
  70. struct NewWindow LeachWindow =
  71. {
  72. 0,  0,                /* Upper left corner X & Y        */
  73. 640, 22,            /* Width and Height. Full width, Two lines tall.    */
  74. 0, 1,                /* Detail & Block Pens(UBYTEs)    */
  75. GADGETUP |            /* IDCMP Flags    (ULONG)            */
  76. CLOSEWINDOW,
  77. SMART_REFRESH |        /* Window Flags    (ULONG)            */
  78. WINDOWCLOSE,
  79.  
  80. swind_gad,            /* Pointer to first gadget.        */
  81. NULL,                /* Pointer to Checkmark image    */
  82. StatWindTitle,        /* Pointer to Window Title        */
  83. NULL,                /* Ptr to Leach's screen        */
  84. NULL,                /* Pointer to bitmap.            */
  85. 00, 00,                /* Min width & height.            */
  86. 00, 00,                /* Max width & height            */
  87. CUSTOMSCREEN        /* Screen type for this window    */
  88. };
  89.  
  90.  
  91. /**************************  INTUITEXT STRUCTURE  *****************************/
  92.  
  93. /*----------------------------------------------------------------------------*
  94.  *    Status display window text. The values of the x's, y's, etc get overwritten
  95.  *    at run time. Any changes to this string must be reflected in the constants
  96.  *    of update_status().
  97.  *----------------------------------------------------------------------------*/
  98.  
  99. UBYTE stext[] = "X1= 110  Y1= 150  X2= 210  Y2= 150  Len= 0100  Slope= 000.0 ";
  100.  
  101. struct IntuiText statustext =
  102. {
  103.     1, 0,            /* Front and Back Pens.        */
  104.     JAM2,            /* Blank out background.    */
  105.     4, 11,            /* Left edge and Top edge.    */
  106.     NULL,            /* Use default font.        */
  107.     &stext[0],        /* Pointer to text string.    */
  108.     NULL            /* Next IntuiText structure    */
  109. };
  110.  
  111.  
  112. /*****************************  BORDER STRUCTURE  *****************************/
  113.  
  114. #define XOR COMPLEMENT
  115.  
  116. /*--------------------------------------------------------------------------*
  117.  * This is the array of ruler screen coordinate pairs. Initialization needs
  118.  * to be kept in sync with the IntuiText string initialization.    Using a 
  119.  * Border struct for one dumb line is probably overkill.
  120.  *--------------------------------------------------------------------------*/
  121.  
  122. short endpoints[4] = {110, 150, 210, 150};
  123.  
  124.  
  125. struct Border ruler =
  126. {
  127. 0, 0,        /* LeftEdge & TopEdge offsets.                         */
  128. 0, 0,        /* Front and back pens. Neither is used in XOR mode. */
  129. XOR,        /* Draw mode. JAM1 is the other choice.                 */
  130. 2,            /* Number of coordinate pairs.                         */
  131. endpoints,    /* Pointer to array of coordinate pairs                 */
  132. NULL        /* Pointer to next Border structure.                 */
  133. };
  134.  
  135.  
  136.  
  137. /*******************************************************************************
  138.  *    Eat shit and die!
  139.  ******************************************************************************/
  140.  
  141. cleanup()
  142. {
  143.  
  144. /* Erase ruler, if it is on. */
  145.  
  146. if ( (SHOWGAD.Flags & SELECTED) && HostRPort )
  147. {
  148.     restore_line();
  149. }
  150. restore_pointer();        /* Make sure Host's mouse pointer is installed.        */
  151.  
  152. /*--------------------------------------------------------------------------*
  153.  * If we know our Task address and have installed it in Host's IDCMP...    
  154.  * Restore the original Host IDCMP flags and return control of its UserPort.
  155.  * Note that the general IDCMP flags are reunited with the IDCMP verification
  156.  * flags, which were stored separately. 
  157.  *---------------------------------------------------------------------- ----*/
  158.  
  159. if (LeachTask && LeachTask == HostUPort->mp_SigTask)
  160. {
  161.     Forbid();
  162.     ModifyIDCMP(HostWind, (HostIDCMPflags | HostVERflags) );
  163.     HostUPort->mp_SigTask = HostTask;
  164.     Permit();
  165. }
  166.  
  167. if (LeachSig && LeachSig != -(1L) )
  168.     FreeSignal(LeachSig);
  169.     
  170. if (HostWind)
  171. {
  172.     /*----------------------------------------------------------------------*
  173.      * ReportMouse() doesn't work with Manx C, so turn the flag off directly.
  174.      * Extract Leach's menu from the Host's menu strip if it exists.
  175.      *----------------------------------------------------------------------*/
  176.  
  177.     HostWind->Flags = HostFlags;
  178.     remove_menu();
  179. }
  180. if (MyPort)
  181. {
  182.     myport_event();
  183.     if (MySig)
  184.         FreeSignal( (long)MySig );
  185.     FreeMem(MyPort, (long)sizeof(struct MsgPort) );
  186. }
  187. if (StatWind)        CloseWindow(StatWind);
  188. if (StatScreen)        CloseScreen(StatScreen);
  189. if (IntuitionBase)    CloseLibrary(IntuitionBase);
  190. if (GfxBase)        CloseLibrary(GfxBase);
  191.  
  192. WBenchToFront();    /* Force WB screen to front in case of error msgs. */
  193.  
  194. exit();
  195.  
  196. } /*  End of cleanup()  */
  197.  
  198.  
  199. /**************************************************************************
  200.  * Create a MsgPort that the Host can return IntuiMessages to. This port is
  201.  * key to the overall scheme for tapping in to the message traffic between
  202.  * the Host and Intuition. Leach is going to alter the ReplyPort in 
  203.  * messages passed on to the Host so they will be ReplyMsg()'d to this port
  204.  * instead of being returned directly to Intuition.
  205.  **************************************************************************/
  206.  
  207. create_myport()
  208. {
  209. MyPort = CreatePort("MYPORT", 0L);
  210. if (!MyPort)
  211. {
  212.     puts("Create of MyPort failed.");
  213.     return(FALSE);
  214. }
  215. MySig = MyPort->mp_SigBit;
  216.  
  217. return(TRUE);
  218.     
  219. } /*  End of create_myport()  */
  220.  
  221.  
  222. /**************************************************************************
  223.  *  Routine finds the menu and item numbers of the Host's QUIT menu item
  224.  *    by inspecting the Host's menu list item by item.
  225.  **************************************************************************/
  226.  
  227. find_quit()
  228. {
  229.  
  230. static UBYTE        target[] = "QUIT";
  231. UBYTE                menu, item;
  232. UBYTE                found_quit;    /* Is NOT the global variable             */
  233. struct Menu            *mptr;        /* Working pointer to current menu.         */
  234. struct MenuItem        *iptr;        /* Working pointer to current menu item. */
  235. UBYTE                *text;        /* Working pointer to menu item text.     */
  236. short                i;            /* Generic integer.                         */
  237.  
  238. mptr = HostMenuStrip;
  239. menu = item = 0;
  240. found_quit  = FALSE;
  241.  
  242. while ( mptr && !found_quit)            /* While more menus...        */
  243. {
  244.     iptr = mptr->FirstItem;
  245.  
  246.     while (iptr && !found_quit)            /* While more menu items...    */
  247.     {
  248.         text = ( (struct IntuiText *)(iptr->ItemFill) )->IText;
  249.         while (*text == ' ')   ++text;    /* Skip leading spaces.    */
  250.  
  251.         for (i = 0; (i < 4) && (toupper(text[i]) == target[i]); ++i);
  252.         if (i == 4)
  253.         {
  254.             found_quit  = TRUE;
  255.             H_quit_item = item;
  256.         }
  257.         else
  258.         {
  259.             ++item;
  260.             iptr = iptr->NextItem;
  261.         }
  262.     }
  263.     if (found_quit)
  264.     {
  265.         H_quit_menu = menu;
  266.     }
  267.     else
  268.     {
  269.         ++menu;
  270.         item = 0;
  271.         mptr = mptr->NextMenu;
  272.     }
  273. }
  274. if (!found_quit)
  275. {
  276.     puts("Can't find Host's QUIT menu item.");
  277.     cleanup(102);
  278. }
  279.  
  280. return( (int)found_quit );
  281.  
  282. } /*  End of find_quit()  */
  283.         
  284.  
  285. /****************************************************************************
  286.  *   This function initializes the color registers for the ViewPort.
  287.  ****************************************************************************/
  288.  
  289. SetStatScrColors()
  290. {
  291.    SetRGB4(StatVP, 0L,  0L,  0L,  0L);        /* Black */
  292.    SetRGB4(StatVP, 1L,  12L, 12L, 12L);        /* White */
  293.    SetRGB4(StatVP, 2L,  0L,  8L,  12L);
  294.    SetRGB4(StatVP, 3L,  15L, 6L,  0L);
  295.  
  296. } /*  End of SetStatScrColors()  */
  297.  
  298.  
  299. /******************************************************************************
  300.  *    Main Routine
  301.  ******************************************************************************/
  302.  
  303. main(argc, argv)
  304. int argc;
  305. char *argv[];
  306. {
  307.  
  308. int         i;
  309.  
  310. /*********************  PROCESS COMMAND LINE ARGUMENTS  ********************/
  311.  
  312. if ( (argv[1][0] == '?') || (argc > 2) )
  313. {
  314.     puts("USAGE: Run Leach after having run a compatible Host program. The");
  315.     puts("       default Host is any of the Digi-View programs. If attaching");
  316.     puts("       Leach to some other Host, specify the Host's screen title");
  317.     puts("       exactly as it appears in the Host's Screen struct and");
  318.     puts("       hopefully on the screen's title bar. For example\n\n");
  319.     puts("               run leach \"Aegis Images V1.1\"\n");
  320.     exit(0);
  321. }
  322.  
  323.  
  324. /**********************  OPEN THE SYSTEM LIBRARIES  *************************/
  325.  
  326. if ( !(GfxBase =  OpenLibrary("graphics.library", 0L) ) )
  327. {
  328.     puts("Can't open Graphics Library.");
  329.     exit();
  330. }
  331. if ( !(IntuitionBase =  OpenLibrary("intuition.library", 0L) ) )
  332. {
  333.     puts("Can't open Intuition Library.");
  334.     cleanup(106);
  335. }
  336.  
  337.  
  338. /*************  FIND HOST'S SCREEN AND OTHER VITAL STATISTICS  **************/
  339.  
  340. Forbid();    /* #################  Shut down multitasking  ################# */
  341.  
  342. HostTitle  = "Digi-View";
  343. if (argc == 2) HostTitle = argv[1];
  344. HostScreen = ( (struct IntuitionBase *) IntuitionBase )->FirstScreen;
  345.  
  346. while (HostScreen)
  347. {
  348.     if (HostScreen->DefaultTitle)
  349.     {
  350.         for (i = 0; HostScreen->DefaultTitle[i] == ' '; ++i);
  351.  
  352.         if ( strcmp(&HostScreen->DefaultTitle[i], HostTitle) )
  353.         {
  354.             HostScreen = HostScreen->NextScreen;
  355.         }
  356.         else    /* It is the Host!    */
  357.         {
  358.             /* Collect some basic info on the Host.    */
  359.  
  360.             HostWind    = HostScreen->FirstWindow;
  361.             HostRPort    = HostWind->RPort; 
  362.             HostUPort    = HostWind->UserPort;
  363.             HostTask    = HostUPort->mp_SigTask;
  364.             HostSig        = HostUPort->mp_SigBit;        /* 0 - 31, not a mask */
  365.             charwidth    = HostRPort->TxWidth;
  366.             charheight    = HostRPort->TxHeight;
  367.             HostFlags    = HostWind->Flags;
  368.             HostMenuStrip  = HostWind->MenuStrip;
  369.             HostIDCMPflags = HostWind->IDCMPFlags;
  370.             HostVERflags   = HostIDCMPflags & (MENUVERIFY | REQVERIFY |
  371.                                                SIZEVERIFY);
  372.             HostIDCMPflags &= ~HostVERflags;
  373.  
  374.             /* HostIDCMPflags now have the Verification flag bits        */
  375.             /* removed and stored separately in HostVERflags.            */
  376.  
  377.             break;            /* Kill while loop  */
  378.         }
  379.     }
  380.     else
  381.     {
  382.         HostScreen = HostScreen->NextScreen;
  383.     }
  384. } /*  end of while (HostScreen)  */
  385.  
  386. /*--------------------------------------------------------------------------*
  387.  * Bump Leach's task priority to one higher than the Host's. We must be able
  388.  * to preempt the Host immediately, when a msg arrives at the Host's IDCMP.
  389.  *--------------------------------------------------------------------------*/
  390.  
  391. LeachTask = FindTask(0L); 
  392. LeachTask->tc_Node.ln_Pri = HostTask->tc_Node.ln_Pri + 1;
  393.  
  394. Permit();    /* #################  Re-enable multitasking  ################# */
  395.  
  396. if ( !(HostScreen && HostWind && HostRPort && HostUPort && HostTask) )
  397. {
  398.     printf("Some Host parameter is NULL. Is %s running?\n", HostTitle);
  399.     cleanup(108);
  400. }
  401.  
  402. H_found_quit = find_quit();        /* Find the Host's QUIT menu item */
  403.  
  404.  
  405. /*--------------------------  Diddle Host's IDCMP  -------------------------*
  406.  *    The objective is to replace the Host's task pointer with one that belongs
  407.  *    to the Leach. There after, Intuition will signal Leach instead of the 
  408.  *    Host when a msg arrives at the Host's UserPort. LeachSig isn't actually
  409.  *    used anywhere in the program. I just wanted to be sure that Leach never
  410.  *    used the signal for anything else. See the file tech-notes for additional
  411.  *    comments on this subject.
  412.  *--------------------------------------------------------------------------*/
  413.  
  414. LeachSig = AllocSignal( (ULONG)HostSig );    /* Returns a long that's 1-32.    */
  415.  
  416. if ( LeachSig != HostSig)
  417. {
  418.     puts("Unable to allocate Leach Signal bit.");
  419.     cleanup(110);
  420. }
  421. HostUPort->mp_SigTask = LeachTask;
  422.  
  423.  
  424. /**********************  LAST MINUTE EMERGENCIES  ***********************/
  425.  
  426. SetStatScrColors();            /* Sets 1st 4 color regs for status screen    */
  427.  
  428. /*----------------------------------------------------------------------*
  429.  * Leach wants to know when the Host window becomes active, so it can
  430.  * ignore the mouse click. If the Host had any verification flags set,
  431.  * they were extracted from HostIDCMPflags so, this is also were Host
  432.  * verification will get shut down for the duration.
  433.  *----------------------------------------------------------------------*/
  434.  
  435. HostIDCMPmods = ACTIVEWINDOW;
  436. ModifyIDCMP(HostWind, HostIDCMPflags | HostIDCMPmods);
  437. HostFlagsmods = 0L;
  438.  
  439. /*--------------------------------------------------------------------------*
  440.  * Initially Leach had trouble working with interlaced Hosts. There was some
  441.  * kind of View/ViewPort conflict, I think. Rather than fix this, I decided
  442.  * to duck the problem by making Leach's screen match the Host's. So, we 
  443.  * check out the Host Screen's height to tell if it's interlaced. This will
  444.  * screw up if not running on an NTSC Amiga.
  445.  *--------------------------------------------------------------------------*/
  446.  
  447. if (HostScreen->Height > 200)
  448. {
  449.     LeachScreen.ViewModes |= LACE;
  450.     LeachScreen.TopEdge = 400 - LeachScreen.Height;
  451. }
  452.  
  453.  
  454. /*****************  OPEN LEACH SCREEN AND STATUS WINDOW  ********************/
  455.  
  456. if (! ( StatScreen = OpenScreen(&LeachScreen) ) )
  457. {
  458.     puts("Couldn't open Leach's Screen.");
  459.     cleanup(112);
  460. }
  461.  
  462. /* Only thing StatVP is currently used for is to set the color registers. */
  463.  
  464. StatVP = &(StatScreen->ViewPort);
  465.  
  466. LeachWindow.Screen = StatScreen;
  467.  
  468. if (! ( StatWind = OpenWindow(&LeachWindow) ) )
  469. {
  470.     puts("Couldn't open Leach's window.");
  471.     cleanup(114);
  472. }
  473. StatRPort = StatWind->RPort;
  474. PrintIText(StatRPort, &statustext, 0L, 0L);        /* Initial endpoints    */
  475. install_menu();
  476. ScreenToFront(HostScreen);
  477.  
  478. event_processor();             /* Currently doesn't return but just in case...    */
  479.  
  480. cleanup(116);                /* Rap it up and quit. */
  481.  
  482. return;
  483.  
  484. } /*  End of main()  */
  485.  
  486.  
  487. /****************************************************************************
  488.  *    A debugging routine that dumps out all the global Host parameters.        *
  489.  
  490. disp_host_params()
  491. {
  492. printf("Host screen title = %s.\n", HostScreen->DefaultTitle);
  493. printf("Host Screen   @ $%lx. Host Window   @ $%lx.\n", HostScreen, HostWind);
  494. printf("Host UserPort @ $%lx. Host RastPort @ $%lx.\n", HostUPort,  HostRPort);
  495. printf("Host Task     @ $%lx. Host SigBit is   $%x.\n", HostTask,   HostSig);
  496. printf("Leach Task    @ $%lx. Leach SigBit is  $%x.\n", LeachTask,  LeachSig);
  497. printf("Leach priority = %d. Host priority = %d.\n", LeachTask->tc_Node.ln_Pri,
  498.                                                      HostTask->tc_Node.ln_Pri);
  499. }
  500. ****************************************************************************/
  501.  
  502.