home *** CD-ROM | disk | FTP | other *** search
/ Mega CD-ROM 1 / megacd_rom_1.zip / megacd_rom_1 / DESQVIEW / DVGLU101.ZIP / TVJNEW.C < prev    next >
C/C++ Source or Header  |  1988-08-13  |  6KB  |  182 lines

  1. /*=======================================================*/
  2. /*  TVJNEW.C                                             */
  3. /*                                                       */
  4. /*  (c) Copyright 1988 Ralf Brown  All Rights Reserved   */
  5. /*  May be freely copied for noncommercial use, so long  */
  6. /*  as this copyright notice remains intact, and any     */
  7. /*  changes are marked in the comment blocks preceding   */
  8. /*  functions.                                           */
  9. /*=======================================================*/
  10.  
  11. #pragma inline
  12.  
  13. #include <string.h>
  14. #include "tvapi.h"
  15.  
  16. static int _TV_newapp_mutex_ = 0 ;
  17.  
  18. static void far (*entry_point)(void) ;
  19.  
  20. /*======================================================*/
  21.  
  22. struct EXEC_block {
  23.        int env ;  /* segment of environment */
  24.        char far *cmdline ;
  25.        struct fcb far *fcb_1 ;
  26.        struct fcb far *fcb_2 ;
  27.        void far *stack ;
  28.        void far (*entry_pt)(void) ;
  29.     } ;
  30.  
  31. /*======================================================*/
  32. /*======================================================*/
  33.  
  34. static void far terminate(void)
  35. {
  36.    TVtask_free(NIL) ;   /* kill task for terminated program */
  37.    geninterrupt(0x20) ; /* insurance */
  38. }
  39.  
  40. /*======================================================*/
  41. /* do final cleanup before jumping to program's entry   */
  42. /* point                                                */
  43. /*======================================================*/
  44.  
  45. static void far launch_app(int parent)
  46. {
  47.    (void) parent ;
  48.    setvect(0x22,(void interrupt (*)(void)) terminate) ;
  49.  
  50.    asm xor ax,ax
  51.    asm push ax     /* for programs expecting a 0 on top of the stack */
  52.    asm push word ptr entry_point+2
  53.    asm push word ptr entry_point
  54.    asm mov ah,62h  /* get PSP segment */
  55.    asm int 21h
  56.    asm mov es,bx   /* DS = ES = PSP */
  57.    asm mov word ptr es:[0Ah],offset terminate
  58.    asm mov word ptr es:[0Ch],cs
  59.    asm mov word ptr es:[16h],bx  /* turn PSP into a parent PSP */
  60.    _TV_newapp_mutex_ = 0 ; /* allow another call to TVspawn... */
  61.    asm mov ds,bx   /* set up segment registers for program */
  62.    asm ret         /* and jump to entry point */
  63. }
  64.  
  65. /*======================================================*/
  66. /* TVspawnve  create new application in current process */
  67. /*   Ralf Brown 5/10/88                                 */
  68. /*   Ralf Brown 8/6/88 made it use vararg list, and     */
  69. /*              renamed to TVspawnve.  TVapp_new now    */
  70. /*              calls this function                     */
  71. /*   Ralf Brown 8/12/88 complete overhaul to hopefully  */
  72. /*              cure random crashing (not done yet)     */
  73. /*======================================================*/
  74.  
  75. OBJECT pascal TVspawnve(OBJECT win,int row,int col,int rows,int cols,
  76.                         int switch_menu,char *program,va_list args,int env)
  77. {
  78.    OBJECT new_app ;
  79.    register char *arg ;
  80.    register int cmd_len = 0 ;
  81.    struct EXEC_block exec_block ;
  82.    char cmd_line[128] ;
  83.    struct fcb fcb1 ;
  84.    struct fcb fcb2 ;
  85.    char far *new_program = (char far *)program ;
  86.  
  87.    /* set up the exec parameter block */
  88.    exec_block.env = env ;
  89.    exec_block.cmdline = (char far *)cmd_line ;
  90.    exec_block.fcb_1 = (struct fcb far *)&fcb1 ;
  91.    exec_block.fcb_2 = (struct fcb far *)&fcb2 ;
  92.  
  93.    /* then concatenate the args to form the commandline */
  94.    (void) va_arg( args, char * ) ;  /* skip argv[0] */
  95.    while ((arg = va_arg(args, char *)) != NULL)
  96.       {
  97.       if (cmd_len >= 126)
  98.          {
  99.          cmd_len = 126 ;
  100.          break ;
  101.          }
  102.       else
  103.          cmd_line[++cmd_len] = ' ' ;  /* separate args by blanks */
  104.       while (*arg && cmd_len < 126)
  105.          cmd_line[++cmd_len] = *arg++ ;
  106.       }
  107.    cmd_line[cmd_len+1] = '\r' ;
  108.    cmd_line[0] = cmd_len ;
  109.    /* now set up the FCBs */
  110.    arg = parsfnm( cmd_line+1, &fcb1, 1 ) ;  /* 1=ignore leading separators */
  111.    if (arg)  /* was first parse successful? */
  112.       (void) parsfnm( arg, &fcb2, 1 ) ;
  113.  
  114.    /* load the program, but don't execute it yet */
  115.    _doserrno = 0 ;  /* assume no error */
  116.    asm push ds
  117.    asm lds dx,new_program
  118.    asm mov bx,ss
  119.    asm mov es,bx
  120.    asm lea bx,exec_block
  121.    asm mov ax,4b01h  /* load but don't execute, DOS 3.x/DESQview version */
  122.    asm int 21h       /* 4b02h on DOS 2.x, but DV takes it over and uses 4b01 */
  123.    asm pop ds
  124.    asm jnc no_error
  125.    _doserrno = _AX ;
  126.    return NIL ;
  127. no_error:
  128.  
  129.    /* we'll be overwriting static vars, so can only have one copy here at a time */
  130. busy_wait:
  131.    asm mov ax,1
  132.    asm lock xchg ax,_TV_newapp_mutex_
  133.    asm or ax,ax
  134.    asm jz wait_done
  135.    TVpause() ;
  136.    asm jmp busy_wait
  137. wait_done:
  138.  
  139.    entry_point = exec_block.entry_pt ;
  140.  
  141.    /* and launch the program if load was successful */
  142.    new_app = TVtask_new(win,NULL,row,col,rows,cols,exec_block.stack,0,
  143.                         launch_app,switch_menu) ;
  144.    if (new_app)
  145.       {
  146.       while (_TV_newapp_mutex_)
  147.          TVpause() ;
  148.       TVtask_post(new_app) ;  /* make sure the task is running */
  149.       }
  150. #if 0
  151.    _AH = 0x50 ;      /* need to restore our PSP segment */
  152.    _BX = _psp ;      /* as known to DOS */
  153.    geninterrupt(0x21) ;
  154. #endif 0
  155.    return new_app ;
  156. }
  157.  
  158. /*======================================================*/
  159. /* TVapp_new  create new application in current process */
  160. /*   Ralf Brown 5/10/88                                 */
  161. /*======================================================*/
  162.  
  163. OBJECT cdecl TVapp_new(OBJECT win,int row,int col,int rows,int cols,
  164.                        int switch_menu,char *program, ...)
  165. {
  166.    return TVspawnve(win,row,col,rows,cols,switch_menu,program,_va_ptr,0) ;
  167. }
  168.  
  169. /*======================================================*/
  170. /*======================================================*/
  171.  
  172. OBJECT cdecl TVspawnle(OBJECT win,int row,int col,int rows,int cols,
  173.                        int switch_menu,char **env,char *program, ...)
  174. {
  175.    int env_seg ;
  176.  
  177. env_seg = 0 ; /* until I figure out how to set it */
  178.    return TVspawnve(win,row,col,rows,cols,switch_menu,program,_va_ptr,env_seg) ;
  179. }
  180.  
  181. /* End of TVJNEW.C */
  182.