home *** CD-ROM | disk | FTP | other *** search
- /*=======================================================*/
- /* TVJNEW.C */
- /* */
- /* (c) Copyright 1988 Ralf Brown All Rights Reserved */
- /* May be freely copied for noncommercial use, so long */
- /* as this copyright notice remains intact, and any */
- /* changes are marked in the comment blocks preceding */
- /* functions. */
- /*=======================================================*/
-
- #pragma inline
-
- #include <string.h>
- #include "tvapi.h"
-
- static int _TV_newapp_mutex_ = 0 ;
-
- static void far (*entry_point)(void) ;
-
- /*======================================================*/
-
- struct EXEC_block {
- int env ; /* segment of environment */
- char far *cmdline ;
- struct fcb far *fcb_1 ;
- struct fcb far *fcb_2 ;
- void far *stack ;
- void far (*entry_pt)(void) ;
- } ;
-
- /*======================================================*/
- /*======================================================*/
-
- static void far terminate(void)
- {
- TVtask_free(NIL) ; /* kill task for terminated program */
- geninterrupt(0x20) ; /* insurance */
- }
-
- /*======================================================*/
- /* do final cleanup before jumping to program's entry */
- /* point */
- /*======================================================*/
-
- static void far launch_app(int parent)
- {
- (void) parent ;
- setvect(0x22,(void interrupt (*)(void)) terminate) ;
-
- asm xor ax,ax
- asm push ax /* for programs expecting a 0 on top of the stack */
- asm push word ptr entry_point+2
- asm push word ptr entry_point
- asm mov ah,62h /* get PSP segment */
- asm int 21h
- asm mov es,bx /* DS = ES = PSP */
- asm mov word ptr es:[0Ah],offset terminate
- asm mov word ptr es:[0Ch],cs
- asm mov word ptr es:[16h],bx /* turn PSP into a parent PSP */
- _TV_newapp_mutex_ = 0 ; /* allow another call to TVspawn... */
- asm mov ds,bx /* set up segment registers for program */
- asm ret /* and jump to entry point */
- }
-
- /*======================================================*/
- /* TVspawnve create new application in current process */
- /* Ralf Brown 5/10/88 */
- /* Ralf Brown 8/6/88 made it use vararg list, and */
- /* renamed to TVspawnve. TVapp_new now */
- /* calls this function */
- /* Ralf Brown 8/12/88 complete overhaul to hopefully */
- /* cure random crashing (not done yet) */
- /*======================================================*/
-
- OBJECT pascal TVspawnve(OBJECT win,int row,int col,int rows,int cols,
- int switch_menu,char *program,va_list args,int env)
- {
- OBJECT new_app ;
- register char *arg ;
- register int cmd_len = 0 ;
- struct EXEC_block exec_block ;
- char cmd_line[128] ;
- struct fcb fcb1 ;
- struct fcb fcb2 ;
- char far *new_program = (char far *)program ;
-
- /* set up the exec parameter block */
- exec_block.env = env ;
- exec_block.cmdline = (char far *)cmd_line ;
- exec_block.fcb_1 = (struct fcb far *)&fcb1 ;
- exec_block.fcb_2 = (struct fcb far *)&fcb2 ;
-
- /* then concatenate the args to form the commandline */
- (void) va_arg( args, char * ) ; /* skip argv[0] */
- while ((arg = va_arg(args, char *)) != NULL)
- {
- if (cmd_len >= 126)
- {
- cmd_len = 126 ;
- break ;
- }
- else
- cmd_line[++cmd_len] = ' ' ; /* separate args by blanks */
- while (*arg && cmd_len < 126)
- cmd_line[++cmd_len] = *arg++ ;
- }
- cmd_line[cmd_len+1] = '\r' ;
- cmd_line[0] = cmd_len ;
- /* now set up the FCBs */
- arg = parsfnm( cmd_line+1, &fcb1, 1 ) ; /* 1=ignore leading separators */
- if (arg) /* was first parse successful? */
- (void) parsfnm( arg, &fcb2, 1 ) ;
-
- /* load the program, but don't execute it yet */
- _doserrno = 0 ; /* assume no error */
- asm push ds
- asm lds dx,new_program
- asm mov bx,ss
- asm mov es,bx
- asm lea bx,exec_block
- asm mov ax,4b01h /* load but don't execute, DOS 3.x/DESQview version */
- asm int 21h /* 4b02h on DOS 2.x, but DV takes it over and uses 4b01 */
- asm pop ds
- asm jnc no_error
- _doserrno = _AX ;
- return NIL ;
- no_error:
-
- /* we'll be overwriting static vars, so can only have one copy here at a time */
- busy_wait:
- asm mov ax,1
- asm lock xchg ax,_TV_newapp_mutex_
- asm or ax,ax
- asm jz wait_done
- TVpause() ;
- asm jmp busy_wait
- wait_done:
-
- entry_point = exec_block.entry_pt ;
-
- /* and launch the program if load was successful */
- new_app = TVtask_new(win,NULL,row,col,rows,cols,exec_block.stack,0,
- launch_app,switch_menu) ;
- if (new_app)
- {
- while (_TV_newapp_mutex_)
- TVpause() ;
- TVtask_post(new_app) ; /* make sure the task is running */
- }
- #if 0
- _AH = 0x50 ; /* need to restore our PSP segment */
- _BX = _psp ; /* as known to DOS */
- geninterrupt(0x21) ;
- #endif 0
- return new_app ;
- }
-
- /*======================================================*/
- /* TVapp_new create new application in current process */
- /* Ralf Brown 5/10/88 */
- /*======================================================*/
-
- OBJECT cdecl TVapp_new(OBJECT win,int row,int col,int rows,int cols,
- int switch_menu,char *program, ...)
- {
- return TVspawnve(win,row,col,rows,cols,switch_menu,program,_va_ptr,0) ;
- }
-
- /*======================================================*/
- /*======================================================*/
-
- OBJECT cdecl TVspawnle(OBJECT win,int row,int col,int rows,int cols,
- int switch_menu,char **env,char *program, ...)
- {
- int env_seg ;
-
- env_seg = 0 ; /* until I figure out how to set it */
- return TVspawnve(win,row,col,rows,cols,switch_menu,program,_va_ptr,env_seg) ;
- }
-
- /* End of TVJNEW.C */
-