void slideshow::show_image()
{
	SDL_Surface *image = m_image_cache->lookup(m_image_index);

	if ( image )
	{
		if ( (m_options->transition != tran_none) && (m_prev_image_index >= 0) && (m_image_index != m_prev_image_index) )
		{
			SDL_Surface *prev_image = m_image_cache->lookup(m_prev_image_index);
			do_transition(prev_image, image);
		}

		SDL_BlitSurface(image, NULL, m_sdl, NULL);
	}
	else
	{
		// For mundane errors such as failures to load pictures, we'll store
		// a placeholder in the image cache which will contain a somewhat
		// more useful error message.  We'll get this if some surface convert/
		// scaling/framing operation failed, for whatever reason.
		SDL_FillRect(m_sdl, NULL, SDL_MapRGB(m_sdl->format, 0, 0, 0));
		center_shadow_text(*m_font, "[unspeakable error]", m_options->width / 2, m_options->height / 2 - 7, 255, 127, 127);
	}

	if ( m_options->display_name )
	{
		draw_picture_name();
		draw_picture_number();
	}

	SDL_Flip(m_sdl);
}
Example #2
0
static int to_state(struct state_t* state,void* input)
{
	int ret;
	do{
		ret=enter_state(state,input);
	}while( state->owner->isrunning && do_transition(state,input) < 0 );

	return exit_state(state,input);
}
Example #3
0
 /*!
  * @brief Sends specific event to the machine
  * @param[in] event Event sent to the state machine
  * @return False if the event would cause state machine to change its state, but due to state machine action
  *         failure, state was not changed and transition did not happen.
  * */
 bool send_event(const EVENT& event) {
     do_on_event_action(event);
     for (const auto& transition : m_transition_table) {
         if (transition.init_state == m_current_state && transition.event == event && do_guard_check(transition)) {
             if (!do_transition(transition)) {
                 return false;
             }
             m_current_state = transition.end_state;
             return true;
         }
     }
     return true;
 }
Example #4
0
void add_action (Action_s *a)
{
	State_s	*s;

	s = find_state(a->address);
	if (!s) {
		s = ezalloc(sizeof(*s));
		s->address = a->address;
		add_state(s);
		init_cir( &s->actions);
	}
	enq_cir( &s->actions, a, link);
	do_transition(s, a);
}
Example #5
0
File: combat.c Project: rj76/kq
/*! \brief Enemies defeated the player
 * \author Josh Bolduc
 * \date created ????????
 * \date updated
 *
 * Play some sad music and set the dead flag so that the game
 * will return to the main menu.
 */
static void enemies_win (void)
{
   play_music ("rain.s3m", 0);
   battle_render (0, 0, 0);
   /*  RB FIXME: rest()?  */
   blit2screen (0, 0);
   kq_wait (1000);
   sprintf (strbuf, _("%s was defeated!"), party[pidx[0]].name);
   menubox (double_buffer, 152 - (strlen (strbuf) * 4), 48, strlen (strbuf), 1,
            BLUE);
   print_font (double_buffer, 160 - (strlen (strbuf) * 4), 56, strbuf,
               FNORMAL);
   blit2screen (0, 0);
   wait_enter ();
   do_transition (TRANS_FADE_OUT, 4);
   alldead = 1;
}
Example #6
0
static YYTOKENTYPE scanDFA( ScanValue *value )
/********************************************/
{
    long                newint;     /* these are used to accumulate parts of */
    VarString           *newstring; /* a new value */
    YYTOKENTYPE         token;
#ifdef SCANDEBUG
    char                debugstring[10];
#endif
    char                *stringFromFile;
    int                 i;

    value->intinfo.type  = SCAN_INT_TYPE_DEFAULT;
    value->string.string = NULL;
    longString = false;

    state( S_START ):
        if( isspace( LookAhead ) ) {
            do_transition( S_START );
        } else if( isdigit( LookAhead ) ) {
            newint = LookAhead - '0';
            newstring = VarStringStart();
            VarStringAddChar( newstring, LookAhead );
            if( LookAhead == '0' ) {
                do_transition( S_HEXSTART );
            } else {
                do_transition( S_DECIMAL );
            }
        } else if( isalpha( LookAhead ) || LookAhead == '_' ) {
            newstring = VarStringStart();
            VarStringAddChar( newstring, LookAhead );
            if( LookAhead == 'l' || LookAhead == 'L' ) {
                do_transition( S_L_STRING );
            }
            do_transition( S_NAME );
        } else switch( LookAhead ) {
            case '"':
                newstring = VarStringStart();  /* don't include the " */
                newLineInString = 0; /* reset newline in string status */
                do_transition( S_STRING );
            case '.':
                newstring = VarStringStart();
                VarStringAddChar( newstring, LookAhead );
                do_transition( S_DOS_FILENAME );
            case EOF:
                DEBUGPUTS( "EOF" )
                return( 0 );                /* yacc wants 0 on EOF */
            case '#':           do_transition( S_POUND_SIGN );
            case '(':           do_transition( S_LPAREN );
            case ')':           do_transition( S_RPAREN );
            case '[':           do_transition( S_LSQ_BRACKET );
            case ']':           do_transition( S_RSQ_BRACKET );
            case '{':           do_transition( S_LBRACE );
            case '}':           do_transition( S_RBRACE );
            case '+':           do_transition( S_PLUS );
            case '-':           do_transition( S_MINUS );
            case '~':           do_transition( S_BITNOT );
            case '!':           do_transition( S_NOT );
            case '*':           do_transition( S_TIMES );
            case '/':           do_transition( S_DIVIDE );
            case '%':           do_transition( S_MOD );
            case '>':           do_transition( S_GT );
            case '<':           do_transition( S_LT );
            case '=':           do_transition( S_EQ );
            case '&':           do_transition( S_BITAND );
            case '^':           do_transition( S_BITXOR );
            case '|':           do_transition( S_BITOR );
            case '?':           do_transition( S_QUESTION );
            case ':':           do_transition( S_COLON );
            case ',':           do_transition( S_COMMA );
            case ';':           do_transition( S_COMMENT );
            case '\\':
                newstring = VarStringStart();
                VarStringAddChar( newstring, LookAhead );
                do_transition( S_DOS_FILENAME );
            default:
                value->UnknownChar = LookAhead;
                do_transition( S_ERROR );
        }
    state( S_L_STRING ):
        if( LookAhead =='"' ) {
            longString = true;
            RESFREE( VarStringEnd( newstring, NULL ) );
            change_state( S_START );
        } else {
            change_state( S_NAME );
        }
    state( S_ERROR ):
        ErrorHasOccured = true;
        return( Y_SCAN_ERROR );

    state( S_COMMENT ):
        if( LookAhead == '\n' || LookAhead == EOF ) {
            do_transition( S_START );
        } else {
            do_transition( S_COMMENT );
        }

    state( S_POUND_SIGN ):
        DEBUGPUTS( "#" )
        return( Y_POUND_SIGN );

    state( S_LPAREN ):
        DEBUGPUTS( "(" )
        return( Y_LPAREN );

    state( S_RPAREN ):
        DEBUGPUTS( ")" )
        return( Y_RPAREN );

    state( S_LSQ_BRACKET ):
        DEBUGPUTS( "[" )
        return( Y_LSQ_BRACKET );

    state( S_RSQ_BRACKET ):
        DEBUGPUTS( "]" )
        return( Y_RSQ_BRACKET );

    state( S_LBRACE ):
        DEBUGPUTS( "{" )
        return( Y_LBRACE );

    state( S_RBRACE ):
        DEBUGPUTS( "}" )
        return( Y_RBRACE );

    state( S_PLUS ):
        DEBUGPUTS( "+" )
        return( Y_PLUS );

    state( S_MINUS ):
        DEBUGPUTS( "-" )
        return( Y_MINUS );

    state( S_BITNOT ):
        DEBUGPUTS( "~" )
        return( Y_BITNOT );

    state( S_NOT ):
        if( LookAhead == '=' ) {
            do_transition( S_NE );
        } else {
            DEBUGPUTS( "!" )
            return( Y_NOT );
        }

    state( S_TIMES ):
        DEBUGPUTS( "*" )
        return( Y_TIMES );

    state( S_DIVIDE ):
        DEBUGPUTS( "/" )
        return( Y_DIVIDE );

    state( S_MOD ):
        DEBUGPUTS( "%" )
        return( Y_MOD );

    state( S_GT ):
        switch( LookAhead ) {
        case '>':       do_transition( S_SHIFTR );
        case '=':       do_transition( S_GE );
        default:
            DEBUGPUTS( ">" )
            return( Y_GT );
        }

    state( S_LT ):
        switch( LookAhead ) {
        case '<':       do_transition( S_SHIFTL );
        case '=':       do_transition( S_LE );
        default:
            DEBUGPUTS( "<" )
            return( Y_LT );
        }

    state( S_EQ ):
        if( LookAhead == '=' ) {
            do_transition( S_ENDEQ );
        } else {
            DEBUGPUTS( "=" )
            return( Y_SINGLE_EQ );
        }

    state( S_BITAND ):
        if( LookAhead == '&' ) {
            do_transition( S_AND );
        } else {
            DEBUGPUTS( "&" )
            return( Y_BITAND );
        }

    state( S_BITXOR ):
        DEBUGPUTS( "^" )
        return( Y_BITXOR );

    state( S_BITOR ):
        if( LookAhead == '|' ) {
            do_transition( S_OR );
        } else {
            DEBUGPUTS( "|" )
            return( Y_BITOR );
        }

    state( S_QUESTION ):
        DEBUGPUTS( "?" )
        return( Y_QUESTION );

    state( S_COLON ):
        DEBUGPUTS( ":" )
        return( Y_COLON );

    state( S_COMMA ):
        DEBUGPUTS( "," )
        return( Y_COMMA );

    state( S_NE ):
        DEBUGPUTS( "!=" )
        return( Y_NE );

    state( S_SHIFTR ):
        DEBUGPUTS( ">>" )
        return( Y_SHIFTR );

    state( S_GE ):
        DEBUGPUTS( ">=" )
        return( Y_GE );

    state( S_SHIFTL ):
        DEBUGPUTS( "<<" )
        return( Y_SHIFTL );

    state( S_LE ):
        DEBUGPUTS( "<=" )
        return( Y_LE );

    state( S_ENDEQ ):
        DEBUGPUTS( "==" )
        return( Y_EQ );

    state( S_AND ):
        DEBUGPUTS( "&&" )
        return( Y_AND );

    state( S_OR ):
        DEBUGPUTS( "||" )
        return( Y_OR );

    state( S_STRING ):
        /* handle double-byte characters */
        i = CharSetLen[LookAhead];
        if( i ) {
            VarStringAddChar( newstring, LookAhead );
            for( ; i > 0; --i ) {
                GetNextChar();
                VarStringAddChar( newstring, LookAhead );
            }
            do_transition( S_STRING );
        }

        // if newline in string was detected, remove all whitespace from
        // begining of the next line
        if( newLineInString ) {
            if( isspace( LookAhead ) ) {
                do_transition( S_STRING );
            } else {
                // non whitespace was detected, reset newline flag, so whitespaces are treated normally
                newLineInString = 0;
            }
        }

        switch( LookAhead ) {
        case '"':           do_transition( S_STRINGEND );
        case '\\':          do_transition( S_ESCAPE_CHAR );
        case '\n':
            if( RcIoIsCOrHFile() ) {
                value->string.string = VarStringEnd( newstring, &(value->string.length) );
                DEBUGPUTS( "STRING" )
                return( Y_STRING );
            } else {
                // MSVC's RC uses this obscure way of handling newline in strings and we follow.
                // First store <space> and then <newline character>. Then on next line, all white
                // spaces from begining of line is removed
                VarStringAddChar( newstring, ' ' );
                VarStringAddChar( newstring, LookAhead );
                newLineInString = 1;
                do_transition( S_STRING );
            }
        default:
            VarStringAddChar( newstring, LookAhead );
            do_transition( S_STRING );
        }
Example #7
0
void reveal(int tgt)
{
	uint32_t c, g = 0, b;
	uint32_t d = 0;
	int draw_x, draw_y;
	char resistance;

	do_transition(TRANS_FADE_OUT, 4);
	Draw.menubox(double_buffer, 84, 56, 17, 13, BLUE);
	sprintf(strbuf, _("Name: %s"), fighter[tgt].name.c_str());
	Draw.print_font(double_buffer, 92, 64, strbuf, FNORMAL);
	sprintf(strbuf, _("Level: %d"), fighter[tgt].lvl);
	Draw.print_font(double_buffer, 92, 72, strbuf, FNORMAL);
	sprintf(strbuf, _("HP: %d/%d"), fighter[tgt].hp, fighter[tgt].mhp);
	Draw.print_font(double_buffer, 92, 80, strbuf, FNORMAL);
	sprintf(strbuf, _("MP: %d/%d"), fighter[tgt].mp, fighter[tgt].mmp);
	Draw.print_font(double_buffer, 92, 88, strbuf, FNORMAL);
	Draw.print_font(double_buffer, 92, 96, _("Earth"), FNORMAL);
	Draw.print_font(double_buffer, 92, 104, _("Black"), FNORMAL);
	Draw.print_font(double_buffer, 92, 112, _("Fire"), FNORMAL);
	Draw.print_font(double_buffer, 92, 120, _("Thunder"), FNORMAL);
	Draw.print_font(double_buffer, 92, 128, _("Air"), FNORMAL);
	Draw.print_font(double_buffer, 92, 136, _("White"), FNORMAL);
	Draw.print_font(double_buffer, 92, 144, _("Water"), FNORMAL);
	Draw.print_font(double_buffer, 92, 152, _("Ice"), FNORMAL);
	for (c = 0; c < 8; c++)
	{
		draw_x = 156;
		draw_y = c * 8 + 97;
		rectfill(double_buffer, draw_x, draw_y, draw_x + 70, draw_y + 6, 3);

		resistance = fighter[tgt].res[c];
		if (resistance < 0)
		{
			// 18: bright red, meaning WEAK defense
			g = 18;
			d = abs(resistance);
		}
		else if (resistance >= 0 && resistance <= 10)
		{
			// 34: bright green, meaning so-so defense
			g = 34;
			d = resistance;
		}
		else if (resistance > 10)
		{
			// 50: bright blue, meaning STRONG defense
			g = 50;
			d = resistance - 10;
		}

		if (d > 0)
		{
			for (b = 0; b < d; b++)
			{
				rectfill(double_buffer, b * 7 + 157, c * 8 + 98, b * 7 + 162,
					c * 8 + 102, g + b);
			}
		}
	}
	Draw.blit2screen(0, 0);
	do_transition(TRANS_FADE_IN, 4);
	Game.wait_enter();
}
Example #8
0
File: combat.c Project: rj76/kq
/*! \brief Really do combat once fighters have been inited
 *
 * \param   bg Background image
 * \param   mus Music
 * \param   is_rnd If !=0 then this is a random combat
 * \returns 1 if battle occurred
 */
static int do_combat (char *bg, char *mus, int is_rnd)
{
   int zoom_step;
   in_combat = 1;
   backart = load_datafile_object (PCX_DATAFILE, bg);
   if (is_rnd) {
      if ((numchrs == 1) && (pidx[0] == AYLA)) {
         hs = rand () % 100 + 1;
         ms = rand () % 3 + 1;
      } else {
         if (numchrs > 1 && (in_party (AYLA) > 0)) {
            hs = rand () % 20 + 1;
            ms = rand () % 5 + 1;
         } else {
            hs = rand () % 10 + 1;
            ms = rand () % 10 + 1;
         }
      }
   } else {
      hs = 10;
      ms = 10;
   }

   /*  RB: do the zoom at the beginning of the combat.  */
   pause_music ();
   set_music_volume ((gmvol / 250.0) * 0.75);
   play_music (mus, 0);
   if (stretch_view == 2) {
      do_transition (TRANS_FADE_OUT, 2);
      clear_bitmap (double_buffer);
      do_transition (TRANS_FADE_IN, 64);
   } else
      /* TT TODO:
       * Change this so when we zoom into the battle, it won't just zoom into the middle
       * of the screen.  Instead, it's going to zoom into the location where the player
       * is, so if he's on the side of the map somewhere...
       */
      for (zoom_step = 0; zoom_step < 9; zoom_step++) {
         poll_music ();

         /*  RB FIXME: stretching when 640x480, stretching when 320x240?  */
         /*            shouldn't one of those be the "common" size, and   */
         /*            therefore not needing to stretch it?               */
         /*            320x240 is the double_buffer size...               */
         if (stretch_view == 1)
            stretch_blit (double_buffer, screen, zoom_step * 16 + xofs,
                          zoom_step * 12 + yofs, 320 - (zoom_step * 32),
                          240 - (zoom_step * 24), 0, 0, 640, 480);

         else
            stretch_blit (double_buffer, screen, zoom_step * 16 + xofs,
                          zoom_step * 12 + yofs, 320 - (zoom_step * 32),
                          240 - (zoom_step * 24), 0, 0, 320, 240);

         /*  RB FIXME: should we vsync here rather than rest?  */
         kq_wait (100);
      }
   snap_togrid ();
   roll_initiative ();
   curx = 0;
   cury = 0;
   vspell = 0;
   combatend = 0;

   /*  RB: execute combat  */
   do_round ();
   unload_datafile_object (backart);
   set_music_volume (gmvol / 250.0);
   resume_music ();
   if (alldead)
      stop_music ();
   steps = 0;
   in_combat = 0;
   timer_count = 0;
   return (1);
}
Example #9
0
/*! \brief Main menu screen
 *
 * This is the main menu... just display the opening and then the menu and
 * then wait for input.  Also handles loading a saved game, and the config menu.
 *
 * \param   c zero if the splash (the bit with the staff and the eight heroes)
 *            should be displayed.
 * \returns 1 if new game, 0 if continuing, 2 if exit
 */
int start_menu (int skip_splash)
{
   int stop = 0, ptr = 0, redraw = 1, a, b;
   DATAFILE *bg;
   BITMAP *staff, *dudes, *tdudes;

#ifdef DEBUGMODE
   if (debugging == 0) {
#endif
      play_music ("oxford.s3m", 0);
      /* Play splash (with the staff and the heroes in circle */
      if (skip_splash == 0) {
         bg = load_datafile_object (PCX_DATAFILE, "KQT_PCX");
         staff = create_bitmap_ex (8, 72, 226);
         dudes = create_bitmap_ex (8, 112, 112);
         tdudes = create_bitmap_ex (8, 112, 112);
         blit ((BITMAP *) bg->dat, staff, 0, 7, 0, 0, 72, 226);
         blit ((BITMAP *) bg->dat, dudes, 80, 0, 0, 0, 112, 112);
         clear_bitmap (double_buffer);
         blit (staff, double_buffer, 0, 0, 124, 22, 72, 226);
         blit2screen (0, 0);

         kq_wait (1000);
         for (a = 0; a < 42; a++) {
            stretch_blit (staff, double_buffer, 0, 0, 72, 226, 124 - (a * 32),
                          22 - (a * 96), 72 + (a * 64), 226 + (a * 192));
            blit2screen (0, 0);
            kq_wait (100);
         }
         for (a = 0; a < 5; a++) {
            color_scale (dudes, tdudes, 53 - a, 53 + a);
            draw_sprite (double_buffer, tdudes, 106, 64);
            blit2screen (0, 0);
            kq_wait (100);
         }
         draw_sprite (double_buffer, dudes, 106, 64);
         blit2screen (0, 0);
         kq_wait (1000);
         destroy_bitmap (staff);
         destroy_bitmap (dudes);
         destroy_bitmap (tdudes);
		 unload_datafile_object(bg);
         /*
            TODO: this fade should actually be to white
            if (_color_depth == 8)
            fade_from (pal, whp, 1);
            else
          */
         do_transition (TRANS_FADE_WHITE, 1);
      }
      clear_to_color (double_buffer, 15);
      blit2screen (0, 0);
      set_palette (pal);
      bg = load_datafile_object (PCX_DATAFILE, "TITLE_PCX");
      for (a = 0; a < 16; a++) {
         clear_to_color (double_buffer, 15 - a);
         masked_blit ((BITMAP *) bg->dat, double_buffer, 0, 0, 0, 60 - (a * 4),
                      320, 124);
         blit2screen (0, 0);
         kq_wait (a == 0 ? 500 : 100);
      }
      if (skip_splash == 0)
         kq_wait (500);
#ifdef DEBUGMODE
   } else {
      set_palette (pal);
      bg = load_datafile_object (PCX_DATAFILE, "TITLE_PCX");
   }
#endif

   reset_world ();

   /* Draw menu and handle menu selection */
   while (!stop) {
      if (redraw) {
         clear_bitmap (double_buffer);
         masked_blit ((BITMAP *) bg->dat, double_buffer, 0, 0, 0, 0, 320, 124);
         menubox (double_buffer, 112, 116, 10, 4, BLUE);
         print_font (double_buffer, 128, 124, _("Continue"), FNORMAL);
         print_font (double_buffer, 128, 132, _("New Game"), FNORMAL);
         print_font (double_buffer, 136, 140, _("Config"), FNORMAL);
         print_font (double_buffer, 144, 148, _("Exit"), FNORMAL);
         draw_sprite (double_buffer, menuptr, 112, ptr * 8 + 124);
         redraw = 0;
      }
      display_credits ();
      blit2screen (0, 0);
      readcontrols ();
      if (bhelp) {
         unpress ();
         show_help ();
         redraw = 1;
      }
      if (up) {
         unpress ();
         if (ptr > 0)
            ptr--;
         else
            ptr = 3;
         play_effect (SND_CLICK, 128);
         redraw = 1;
      }
      if (down) {
         unpress ();
         if (ptr < 3)
            ptr++;
         else
            ptr = 0;
         play_effect (SND_CLICK, 128);
         redraw = 1;
      }
      if (balt) {
         unpress ();
         if (ptr == 0) {        /* User selected "Continue" */
            if (snc[0] == 0 && snc[1] == 0 && snc[2] == 0 && snc[3] == 0
                && snc[4] == 0)
               stop = 2;
            else if (saveload (0) == 1)
               stop = 1;
            redraw = 1;
         } else if (ptr == 1) { /* User selected "New Game" */
            stop = 2;
         } else if (ptr == 2) { /* Config */
            clear (double_buffer);
            config_menu ();
            redraw = 1;

            /* TODO: Save Global Settings Here */
         } else if (ptr == 3) { /* Exit */
            unload_datafile_object (bg);
            klog (_("Then exit you shall!"));
            return 2;
         }
      }
   }
   unload_datafile_object (bg);
   if (stop == 2) {
      /* New game init */
      for (a = 0; a < MAXCHRS; a++)
         memcpy (&party[a], &players[a].plr, sizeof (s_player));
      init_players ();
      memset (progress, 0, SIZE_PROGRESS);
      memset (treasure, 0, SIZE_TREASURE);
      numchrs = 0;
      for (a = 0; a < NUMSHOPS; a++) {
         for (b = 0; b < SHOPITEMS; b++)
            shops[a].items_current[b] = shops[a].items_max[b];
      }
      for (b = 0; b < 2; b++) {
         for (a = 0; a < MAX_INV; a++)
            g_inv[a][b] = 0;
      }
   }
   return stop - 1;
}
Example #10
0
Errcode render_composite(Boolean do_preview)
/*****************************************************************************
 * Main entry point to this module.   Fill in the initial fields of ccb
 * (see comment on struct compo_cb in composit.h) before calling this.
 ****************************************************************************/
{
Errcode err;
SHORT flx_ix, exit_flx_ix;
Initpframe init_pframe = NULL;
Getmask get_mask = NULL;
Closepframe close_pframe = NULL;

	ccb.preview_mode = do_preview;
	ccb.preview_frame = 0;

	if(vs.co_type == COMP_MASK)
	{
		if(reload_mask_cel() < Success)
			return(Err_abort);
		scale_fcel_to_screen(ccb.mask_cel,vb.pencel);
	}
	else
		free_fcel(&ccb.mask_cel);

	set_abort_verify(comp_abort_verify, NULL);

	exit_flx_ix = flx_ix = vs.frame_ix;

	if((err = sv_fli(ram_tflx_name)) < Success)
		goto save_error;
	close_tflx();

	free_fcel(&ccb.fcela);
	if((err = load_fli_fcel(ram_tflx_name,NULL,NULL,&ccb.fcela)) < Success)
		goto error;

/* scale cels to screen and center them */

	clear_fcel_xform(ccb.fcela);
	clear_fcel_xform(ccb.fcelb);
	if(vs.co_matchsize)
		scale_fcel_to_screen(ccb.fcelb,vb.pencel);

	center_fcel_in_screen(ccb.fcela,vb.pencel);
	center_fcel_in_screen(ccb.fcelb,vb.pencel);

/*** set start and end and pre-load frame count and index values */

	ccb.clearc = -1; /* for now ignore color 0 */

	if(vs.co_b_first)
	{
		ccb.start_cel = ccb.fcelb;
		ccb.end_cel = ccb.fcela;
		ccb.cfit_type = INVERT_CFITMODE(vs.co_cfit);
	}
	else
	{
		ccb.start_cel = ccb.fcela;
		ccb.end_cel = ccb.fcelb;
		ccb.cfit_type = vs.co_cfit;
	}

	ccb.cela_start = 0;
	ccb.cela_frames = ccb.start_cel->flif.hdr.frame_count;
	ccb.cela_transtart = ccb.cela_start + ccb.cela_frames;

	ccb.celb_tailstart = ccb.celb_start = 0;
	ccb.celb_frames = ccb.end_cel->flif.hdr.frame_count;

	if(vs.co_still)
	{
		ccb.cela_transtart -= 1;
	}
	else
	{
		ccb.cela_frames -= ccb.transition_frames;
		ccb.cela_transtart -= ccb.transition_frames;
		ccb.celb_frames -= ccb.transition_frames;
		ccb.celb_tailstart += ccb.transition_frames;
	}

	ccb.total_frames =
		ccb.cela_frames + ccb.celb_frames + ccb.transition_frames;

	/* open new tempflx for new total frames */

	if((err = empty_tempflx(ccb.total_frames)) < Success)
		goto error;

	flix.hdr.speed = ccb.fcela->flif.hdr.speed; /* preserve speed */
	flix.hdr.frame_count = 0;  /* this one is REALLY empty */

	/* set finish up index to be same position on initial fli */

	if(vs.co_b_first)
	{
		flx_ix += ccb.cela_frames;
		if(vs.co_still)
			flx_ix += ccb.transition_frames;
		else
			flx_ix -= ccb.transition_frames;
	}

	err = Err_unimpl; /* anything not hit by switch */

	init_pframe = init_masked_pframe;
	switch(vs.co_type)
	{
		case COMP_CUT:
			err = do_cut();
			break;
		case COMP_CIRCLE:
			get_mask = make_circle_mask;
			goto call_wipe;
		case COMP_HWEDGE:
			get_mask = make_hwedge_mask;
			goto call_wipe;
		case COMP_VERTW:
			get_mask = make_vert_mask;
			goto call_wipe;
		case COMP_BOX:
			get_mask = make_box_mask;
			goto call_wipe;
		case COMP_VWEDGE:
			get_mask = make_vwedge_mask;
			goto call_wipe;
		case COMP_HORIZW:
			get_mask = make_horiz_mask;
			goto call_wipe;
		case COMP_BOXLTOP:
		case COMP_BOXRTOP:
		case COMP_BOXRBOT:
		case COMP_BOXLBOT:
			get_mask = make_corbox_mask;
			goto call_wipe;
		case COMP_VENETIAN:
			get_mask = make_venetian_mask;
			goto call_wipe;
		case COMP_LOUVER:
			get_mask = make_louver_mask;
			goto call_wipe;
		case COMP_DIAGTOP:
			get_mask = make_tdiag_mask;
			goto call_wipe;
		case COMP_DIAGBOT:
			get_mask = make_bdiag_mask;
			goto call_wipe;
		case COMP_MASK:
			init_pframe = init_flicel_mask;
			get_mask = get_flicel_mask;
			close_pframe = cleanup_flicel_mask;
			goto call_wipe;
		case COMP_DISSOLVE:
			get_mask = make_dissolve_mask;
			goto call_wipe;
		case COMP_BOXIL:
			init_pframe = init_boxil_mask;
			get_mask = get_boxil_mask;
			close_pframe = cleanup_boxil_mask;
			goto call_wipe;
		case COMP_DIAMOND:
			get_mask = make_diamond_mask;
			goto call_wipe;
call_wipe:
			err = do_transition(init_pframe, get_mask, close_pframe);
			break;
		default:
			err = Err_bad_input;
			break;
	}

	if(err < Success)
		goto error;
	if(ccb.preview_mode)
	{
		err = Err_abort;
		goto error;
	}

	exit_flx_ix = flx_ix;
	free_fcel(&ccb.fcelb); /* done with this now */
	dirties();

error:

	free_fcel(&ccb.fcela); /* cel a was only temporary */

	if( (err >= Success)
		 || (make_tempflx(ram_tflx_name,0) < Success))
	{
		clear_flipath(ccb.tflxpath);
	}

	/* if all done and new tempflx is ok or
	 * we re-loaded tempflx from saved temp file seek to previous
	 * position */

	exit_flx_ix = wrap_frame(exit_flx_ix);
	vs.bframe_ix = 0; /* no no no */
	fli_abs_tseek(undof,exit_flx_ix);
	if(err < Success)
		pj_delete(bscreen_name);
	vs.frame_ix = exit_flx_ix;

	update_flx_path(&flix,&ccb.tflxpath->fid,ccb.tflxpath->path);

	if(ccb.fcelb && ccb.fcelb->rc == NULL) /* will be freed if success */
	{
		if(alloc_fcel_raster(ccb.fcelb) < Success)
			free_fcel(&ccb.fcelb);
	}

save_error:
	err = softerr(err,"join_flis");
	set_abort_verify(NULL, NULL);
	pj_delete(ram_tflx_name);
	zoom_unundo();
	return(err);
}