Example #1
0
void 
LevelsCache::get_levels(vtime_t _time, sample_t _levels[NCHANNELS], bool drop)
{
  memcpy(_levels, levels_cache[end], sizeof(sample_t) * NCHANNELS);
  if (_time < 0)
    _time = levels_time[pos];

  int b, e, ch;
  int i;

  b = end;
  e = end;
  while (levels_time[b] < _time && b != pos)
  {
    e = b;
    b = next_pos(b);
  };

  i = end;
  while (i != e)
  {
    for (ch = 0; ch < NCHANNELS; ch++)
      if (levels_cache[i][ch] > _levels[ch])
        _levels[ch] = levels_cache[i][ch];

    i = next_pos(i);
  }

  if (drop)
    end = i;
}
Example #2
0
void
LevelsCache::add_levels(vtime_t _time, sample_t _levels[NCHANNELS])
{
  pos = next_pos(pos);
  if (pos == end)
    end = next_pos(end);

  levels_time[pos] = _time;
  memcpy(levels_cache[pos], _levels, sizeof(sample_t) * NCHANNELS);
}
Example #3
0
File: edit.c Project: vigna/ne
static int save_space(line_desc * const ld, const int tab_size, const encoding_type encoding) {
	if (pa_space) free(pa_space);
	pa_space  = NULL;
	pa_space_len = 0;
	pa_space_pos = 0;

	if (!ld->line) return 0; /* No data on this line. */

	int64_t pos = 0;
	while(pos < ld->line_len && isasciispace(ld->line[pos])) pos = next_pos(ld->line, pos, encoding);

	if (pos == ld->line_len) return 0; /* Blank lines don't count. */

	pa_space_pos = pos;
	pa_space_len = calc_width(ld, pos, tab_size, encoding);

	if (pos == 0) {
		return 1;
	}

	if ((pa_space = malloc(pos))) {
		memcpy(pa_space, ld->line, pos);
		return 1;
	}

	return 0;
}
/* call from master task. caller should notify llat task if necessary */
static uint32_t post(DISP_T *disp, uint32_t win, uint32_t swap_interval)
{
   uint32_t slot;
   MEM_HANDLE_T handle;

   /* wait for a free slot */
   while ((next_pos(disp->in_use.post, disp->in_use.n) - disp->in_use.on) > SLOTS_N) {
      khrn_sync_master_wait();
   }
   khrn_barrier();

   /* fill it in */
   slot = disp->in_use.post & (SLOTS_N - 1);
   /* we take a copy of the KHRN_IMAGE_T here as in the swap interval 0 case the
    * width/height/stride could change before we get around to putting the image
    * on the display */
   handle = disp->in_use.images[slot & (next_power_of_2(disp->in_use.n) - 1)];
   disp->in_use.slots[slot].image = *(KHRN_IMAGE_T *)mem_lock(handle);
   mem_unlock(handle);
   disp->in_use.slots[slot].win = win;
   disp->in_use.slots[slot].swap_interval = swap_interval;
   disp->in_use.slots[slot].ready = false;
   disp->in_use.slots[slot].skip = false;
   disp->in_use.slots[slot].wait_posted = false;

   /* advance the post counter */
   advance_pos(&disp->in_use.post, disp->in_use.n);

   return slot;
}
Example #5
0
static void* handle_send(void* qp)
{
	qpos_t* pointer = (qpos_t*)qp;
	if (pointer)
	{
		char buf[MESSAGE_LIMIT];
		size_t len = 0;
		int written;
	    struct pollfd poller;
	    poller.fd = *(pointer->cfd);
	    poller.events = POLLWRNORM;
	    int finish = 0;
	    while (1) {
	    	pthread_rwlock_rdlock(&global_lock);
	    	if (pointer->pos == QUEUE_BACKLOG) 
	    	{
	    		finish = 1;
	    	}
	        else if (pointer->pos != mpos) 
	        {
	            message_t* msg_container = messages + pointer->pos;
	            memcpy(buf, msg_container->msg, msg_container->len);
	            len = msg_container->len;
	            pointer->pos = next_pos(pointer->pos);
	            pthread_mutex_lock(&msg_container->mutex);
	            msg_container->num++;
	            pthread_mutex_unlock(&msg_container->mutex);
	        }
	        pthread_rwlock_unlock(&global_lock);
	        if (finish) break;
	        poll(&poller, 1, INFTIM);
	        if (poller.revents & POLLWRNORM)
	        {
	        	while (len > 0)
		        {
		        	written = write(*(pointer->cfd), buf, len);
		        	if (written <= 0)
		        	{
		        		break;
		        	}
		        	else
		        	{
		        		len -= written;
		        		memmove(buf, buf + written, len);
		        	}
		        }
		        if (len > 0)
		        {
		        	break;
		        }	
	        }
	        len = 0;
	    }
	    printf("HS: someone disconnected\n");
	    pthread_rwlock_wrlock(&global_lock);
	    pointer->pos = QUEUE_BACKLOG;
	    pthread_rwlock_unlock(&global_lock);
	}
	return NULL;
}
Example #6
0
File: edit.c Project: vigna/ne
int center(buffer * const b) {

	line_desc * const ld = b->cur_line_desc;
	const int right_margin = b->opt.right_margin ? b->opt.right_margin : ne_columns;

	int64_t
		len,
		start_pos = 0,
		end_pos = ld->line_len;

	while(start_pos < ld->line_len && isasciispace(ld->line[start_pos])) start_pos = next_pos(ld->line, start_pos, b->encoding);
	if (start_pos == ld->line_len) return OK;
	while(isasciispace(ld->line[prev_pos(ld->line, end_pos, b->encoding)])) end_pos = prev_pos(ld->line, end_pos, b->encoding);

	len = b->encoding == ENC_UTF8 ? utf8strlen(&ld->line[start_pos], end_pos - start_pos) : end_pos - start_pos;
	if (len >= right_margin) return OK;

	b->cur_pos = -1;
	start_undo_chain(b);

	delete_stream(b, ld, b->cur_line, end_pos, ld->line_len - end_pos);
	delete_stream(b, ld, b->cur_line, 0, start_pos);
	insert_spaces(b, ld, b->cur_line, 0, (right_margin - len) / 2);

	end_undo_chain(b);

	return OK;
}
Example #7
0
bool MPSegment::build_DAG( string &sentence, SegmentContext &segContext )
{
    // 初始化每个char节点
    vector<char>    vecLen; 
    size_t          char_count;

    Utf8_LetterLen( sentence, vecLen );
    char_count  = vecLen.size();


    // 构建每个节点DAG
    size_t          i(0), j(0), k(0);
    size_t          start_pos(0), next_pos(0), num(0);
    STWordInfo      wInfo;
    STCharNodeInfo  *pNode(NULL);
    STResultPair    result_pair[20];
    const char      *pSz = sentence.c_str();
    

    segContext.clear();
    segContext.resize( char_count );
    for ( i=0; i<char_count; ++i )
    {
        //cout<< "build dag " << i << "\tstart_pos: "<< start_pos<< "\tcharlen: "<< int(vecLen[i]) << endl;
        pNode = &segContext[i];
        pNode->ch = sentence.substr( start_pos, int(vecLen[i]) );

        num = m_pDict->commonPrefixSearch( pSz+start_pos, result_pair, 20 );
        for ( j=0; j<num; ++j )
        {
            //cout << "common search: "<< i << "\t" << result_pair[j].len << "\t" << result_pair[j].val << endl;

            for ( k=i; k<char_count; ++k )
            {
                result_pair[j].len -= vecLen[k]; 
                if ( 0 == result_pair[j].len )
                    break;
            }

            m_pDict->getWordInfo( result_pair[j].val, pNode->dag[k+1] );
        }
        
    
        // single char, assign the min weight
        wInfo.clear();
        wInfo.word      = pNode->ch;
        wInfo.freq      = m_pDict->getMinFreq( );
        wInfo.logFreq   = m_pDict->getMinLogFreq( );
        pNode->dag[i+1] = wInfo;

        start_pos += vecLen[i];
    }


    return true;    
}
void
CApp::verify_winner(int id) {
  if (check_pos(id, next_pos(id, 0, 1), 0, 1) ||
      check_pos(id, next_pos(id, 1, 0), 1, 0) ||
      (check_anti_diag(id) &&
       check_pos(id, next_pos(id, 1, -1), 1, -1)) ||
      (check_diag(id) &&
       check_pos(id, next_pos(id, 1, 1), 1, 1))) {
    if (grid[id] == GRID_TYPE_X)
      result = FINAL_X_WON;
    else
      result = FINAL_O_WON;
    finish = true;
  }
  if (grid_used == MATRIX_SIZE * MATRIX_SIZE) {
    result = FINAL_DRAW;
    finish = true;
  }
}
bool
CApp::check_pos(int id, int pos, int x_dir, int y_dir) {
  if (id == pos)
    return true;

  if (grid[id] != grid[pos])
    return false;

  return check_pos(id, next_pos(pos, x_dir, y_dir), x_dir, y_dir);
}
Example #10
0
      void push(T const item)
      {
        // if (full())
        //   throw std::runtime_error("buffer is full");

        head_ = next_pos();
        data_[head_] = item;

        if (size_ < data_.size())
          size_++;
      }
Example #11
0
File: input.c Project: dmt4/ne
static void input_move_right(const bool do_refresh) {
	const int prev_pos = pos;

	if (pos < len) {
		const int x_delta = get_char_width(&input_buffer[pos], encoding);
		pos = next_pos(input_buffer, pos, encoding);

		assert(pos <= len);

		if ((x += x_delta) >= ne_columns) {
			const int shift = x - (ne_columns - 1);
			int width = 0;

			do {
				width += get_char_width(&input_buffer[offset], encoding);
				offset = next_pos(input_buffer, offset, encoding);
			} while(width < shift && offset < len);

			assert(offset < len);

			x -= width;

			if (char_ins_del_ok) {
				int i, j;
				move_cursor(ne_lines - 1, start_x);
				delete_chars(width);
				move_cursor(ne_lines - 1, x - x_delta);
				output_char(get_char(&input_buffer[prev_pos], encoding), 0, encoding);

				i = x;
				j = pos;
				while(j < len && i + (width = get_char_width(&input_buffer[j], encoding)) < ne_columns) {
					output_char(get_char(&input_buffer[j], encoding), 0, encoding);
					i += width;
					j = next_pos(input_buffer, j, encoding);
				}
			}
			else if (do_refresh) input_refresh();
		}
	}
}
Example #12
0
File: edit.c Project: vigna/ne
static int is_part_of_paragraph(const line_desc * const ld, const int tab_size, int64_t * const first_non_blank, const encoding_type encoding) {
	*first_non_blank = -1;
	if (!ld->line) return 0;

	int64_t pos = 0;
	while (pos < ld->line_len && isasciispace(ld->line[pos])) pos = next_pos(ld->line, pos, encoding);
	if (pos < ld->line_len && calc_width(ld, pos, tab_size, encoding) == pa_space_len) {
		*first_non_blank = pos;
		return 1;
	}
	return 0;
}
Example #13
0
static void new_message(const char *msg, size_t len)
{
	pthread_rwlock_wrlock(&global_lock);
	message_t* msg_container = messages + mpos;
	pthread_mutex_lock(&msg_container->mutex);
	if (msg_container->expected != msg_container->num)
	{
		qpos_t* cur;
		for(cur = qpos_list; cur != NULL; cur = cur->next)
		{
			if (cur->pos == mpos)
			{
				cur->pos = next_pos(mpos);
			}
		}
	}
	msg_container->expected = listener_count;
	msg_container->num = 0;
	memcpy(msg_container->msg, msg, len);
	msg_container->len = len;
	mpos = next_pos(mpos);
	pthread_mutex_unlock(&msg_container->mutex);
	pthread_rwlock_unlock(&global_lock);
}
Example #14
0
File: edit.c Project: vigna/ne
int auto_indent_line(buffer * const b, const int64_t line, line_desc * const ld, const int64_t up_to_col) {

	line_desc * const prev_ld = (line_desc *)ld->ld_node.prev;

	if (!prev_ld->ld_node.prev || prev_ld->line_len == 0) return 0;
	assert_line_desc(prev_ld, b->encoding);

	int c;
	int64_t pos = 0;
	for(int64_t col = 0; pos < prev_ld->line_len && ne_isspace(c = get_char(&prev_ld->line[pos], b->encoding), b->encoding); ) {
		col += (c == '\t' ? b->opt.tab_size - col % b->opt.tab_size : 1);
		if (col > up_to_col) break;
		pos = next_pos(prev_ld->line, pos, b->encoding);
	}
	if (pos) insert_stream(b, ld, line, 0, prev_ld->line, pos);
	return pos;
}
Example #15
0
File: edit.c Project: vigna/ne
int word_wrap2(buffer * const b) {
	static char avcmd[16];

	if (b->cur_pos > b->cur_line_desc->line_len) return OK;

	bool non_blank_added = false;
	int avshift;
	char * line = b->cur_line_desc->line;
	int64_t pos, original_line;

	/* If the char to our left is a space, we need to insert
	   a non-space to attach our WORDWRAP_BOOKMARK to because
	   spaces at the split point get removed, which effectively
	   leaves our bookmark on the current line. */
	delay_update();
	pos = prev_pos(line, b->cur_pos, b->encoding);
	if (pos >= 0 && (non_blank_added = ne_isspace(get_char(&line[pos], b->encoding), b->encoding))) {
		start_undo_chain(b);
		insert_one_char(b, b->cur_line_desc, b->cur_line, b->cur_pos, 'X');
		line = b->cur_line_desc->line;
		goto_pos(b, next_pos(line, b->cur_pos, b->encoding));
	}
	b->bookmark[WORDWRAP_BOOKMARK].pos   = b->cur_pos;
	b->bookmark[WORDWRAP_BOOKMARK].line  = original_line = b->cur_line;
	b->bookmark[WORDWRAP_BOOKMARK].cur_y = b->cur_y;
	b->bookmark_mask |= (1 << WORDWRAP_BOOKMARK);
	paragraph(b);
	goto_line_pos(b, b->bookmark[WORDWRAP_BOOKMARK].line, b->bookmark[WORDWRAP_BOOKMARK].pos);
	line = b->cur_line_desc->line;
	b->bookmark[WORDWRAP_BOOKMARK].cur_y += b->bookmark[WORDWRAP_BOOKMARK].line - original_line;
	if (avshift = b->cur_y - b->bookmark[WORDWRAP_BOOKMARK].cur_y) {
		snprintf(avcmd, 16, "%c%d", avshift > 0 ? 'T' :'B', avshift > 0 ? avshift : -avshift);
		adjust_view(b, avcmd);
	}
	b->bookmark_mask &= ~(1 << WORDWRAP_BOOKMARK);
	if (non_blank_added) {
		goto_pos(b, prev_pos(b->cur_line_desc->line, b->cur_pos, b->encoding));
		delete_one_char(b, b->cur_line_desc, b->cur_line, b->cur_pos);
		end_undo_chain(b);
	}
	return stop ? STOPPED : OK;
}
Example #16
0
sigar_rma_add_sample(sigar_rma_stat_t * rma,
		float value, sigar_int64_t cur_time_sec)
{
	if (rma == NULL) {
		return -1;
	}

	sigar_rma_sample_t *sample = &rma->samples[rma->current_pos];

   	sample->value = value;

	if (cur_time_sec != 0) {
		sample->stime = cur_time_sec;
	} else {
		sample->stime = sigar_time_now_millis() / 1000;
	}

	rma->current_pos = next_pos(rma, rma->current_pos);

	return 0;
}
Example #17
0
void Snake::render_tick()
{
  byte x = _head_x;
  byte y = _head_y;
  byte dir;

  // Draw head
  set_xy(x, y, 1);

  // Delete tail
  for (int i=0; i < _snake_len; i++)
 {
    dir = ~(get_element(i)) & 3;

    next_pos((direction)dir, &x, &y);
    if (i == _snake_len - 1) {
        set_xy(x, y, 0);
    }
  }

  // Draw food
  if (_food_x > 0 && _food_y > 0)
    set_xy(_food_x, _food_y, 1);
}
Example #18
0
void ProgResolutionIBW::edgeWidth(const MultidimArray<double> &volCoeffs,
                                  const MultidimArray<double> &edges,
                                  MultidimArray <double>& widths, const Matrix1D<double> &dir,
                                  double step) const
{
    double forward_count, backward_count, slope;
    Matrix1D<double> pos_aux_fw(3), pos_aux_bw(3), pos(3), pos_aux(3), next_pos(3), Kdir;

    Kdir=step*dir;

    //Visit all elements in volume
    FOR_ALL_ELEMENTS_IN_ARRAY3D(edges)
    {
        //Check for border pixels
        if (A3D_ELEM(edges,k,i,j)!=0)
        {
            //reset all counters
            forward_count=0;
            backward_count=0;
            VECTOR_R3(pos_aux_fw,j,i,k);
            pos_aux_bw=pos=pos_aux_fw;

            //find out if pixel magnitude grows or decreases
            pos_aux=pos;
            pos_aux+=dir;
            double value_plus_dir=volCoeffs.interpolatedElementBSpline3D(XX(pos_aux),YY(pos_aux),ZZ(pos_aux));

            pos_aux=pos;
            pos_aux-=dir;
            double value_minus_dir=volCoeffs.interpolatedElementBSpline3D(XX(pos_aux),YY(pos_aux),ZZ(pos_aux));

            slope=value_plus_dir-value_minus_dir;

            double sign;
            if (slope>0)
                sign=1;
            else
                sign=-1;

            //current_pixel is multiplied by the sign, so only one condition is enough to detect an
            //extremum no matter if the pixel values increase or decrease
            double current_pixel=sign*volCoeffs.interpolatedElementBSpline3D
                                 (XX(pos_aux_fw),YY(pos_aux_fw),ZZ(pos_aux_fw));

            double next_pixel;
            bool not_found;

            //Search for local extremum ahead of the edge in the given direction
            do
            {
                not_found=true;
                next_pos=pos_aux_fw+Kdir;
                next_pixel=sign*volCoeffs.interpolatedElementBSpline3D
                           (XX(next_pos),YY(next_pos),ZZ(next_pos));

                if(next_pixel>current_pixel)
                {
                    current_pixel=next_pixel;
                    pos_aux_fw=next_pos;
                    forward_count++;
                }
                else
                {
                    not_found=false;
                }
            }
            while(not_found);

            current_pixel=sign*volCoeffs.interpolatedElementBSpline3D
                          (XX(pos_aux_bw),YY(pos_aux_bw),ZZ(pos_aux_bw));

            //Search for local extremum behind of the edge in the given direction
            do
            {
                not_found=true;
                next_pos=pos_aux_bw-Kdir;
                next_pixel=sign*volCoeffs.interpolatedElementBSpline3D
                           (XX(next_pos),YY(next_pos),ZZ(next_pos));

                if(next_pixel<current_pixel)
                {
                    current_pixel=next_pixel;
                    pos_aux_bw=next_pos;
                    backward_count++;
                }
                else
                {
                    not_found=false;
                }
            }
            while(not_found);

            //If the width found for this position is smaller than the one stores in edges volume
            //before it is overwritten
            if ((forward_count+backward_count)<A3D_ELEM(widths,k,i,j))
            {
                A3D_ELEM(widths,k,i,j)=forward_count+backward_count;
            }
        }
    }
}
Example #19
0
File: edit.c Project: vigna/ne
int paragraph(buffer * const b) {
	line_desc *ld = b->cur_line_desc, *start_line_desc = ld;

	if (!ld->line) return line_down(b);

	/* Establish appropriate leading space. This will be taken from the line
      following the current line if it is non-blank. Otherwise it will be
      taken from the current line. Save a copy of it for later as space[]. **/

	if ( !(    (ld->ld_node.next->next && save_space((line_desc *)ld->ld_node.next, b->opt.tab_size, b->encoding))
	        || save_space(ld, b->opt.tab_size, b->encoding) )
	   ) return line_down(b);

	int64_t pos = b->cur_pos;
	b->cur_pos = -1;

	start_undo_chain(b);

	/* This insertion and deletion of a single character ensures
	   that the cursor ends up here after an undo. */
	int64_t line = b->cur_line;
	insert_one_char(b, ld, line, 0, ' ');
	delete_stream(b, ld, line, 0, 1);

	const int right_margin = b->opt.right_margin ? b->opt.right_margin : ne_columns;
	bool done;

	do {
		done = true; /* set this to false if we do any work in the loop. */

		trim_trailing_space(b, ld, line, b->encoding);

		/* Suck up subsequent lines until this one is long enough to need splitting */
		while ((calc_width(ld, ld->line_len, b->opt.tab_size, b->encoding) <= right_margin) &&
		       ld->ld_node.next->next && is_part_of_paragraph((line_desc *)ld->ld_node.next, b->opt.tab_size, &pos, b->encoding)) {
			line_desc *ld_next = (line_desc *)ld->ld_node.next;
			insert_one_char(b, ld, line, ld->line_len, ' ');
			if (pos) delete_stream(b, ld_next, line + 1, 0, pos); /* pos was set by is_part_of_paragraph() above. */
			delete_stream(b, ld, line, ld->line_len, 1);          /* joins next line to this one */
			trim_trailing_space(b, ld, line, b->encoding);
			done = false;
		}

		if (calc_width(ld, ld->line_len, b->opt.tab_size, b->encoding) > right_margin) {
			int64_t spaces;
			int64_t split_pos;
			/* Skip past leading spaces... */
			pos = 0;
			while(pos < ld->line_len && isasciispace(ld->line[pos]))
				pos = next_pos(ld->line, pos, b->encoding);

			/* Find the split point */
			split_pos = spaces = 0;
			while (pos < ld->line_len && (calc_width(ld, pos, b->opt.tab_size, b->encoding) < right_margin || ! split_pos)) {
				if (isasciispace(ld->line[pos])) {
					split_pos = pos;
					spaces = 0;
					while (pos < ld->line_len && isasciispace(ld->line[pos])) {
						pos = next_pos(ld->line, pos, b->encoding);
						spaces++;
					}
				}
				else pos = next_pos(ld->line, pos, b->encoding);
			}
			if (split_pos) {
				done = false;
				/* Remove any space at the split point. */
				if (spaces) delete_stream(b, ld, line, split_pos, spaces);

				/* Split the line at the split point.  (We are done with this line) */
				insert_one_line(b, ld, line, split_pos);

				/* Make the new next line the current line **/
				if (ld->ld_node.next->next) {
					ld = (line_desc *)ld->ld_node.next;
					line++;
					if (pa_space && pa_space_len && pa_space_pos)
						insert_stream(b, ld, line, 0, pa_space, pa_space_pos);
					trim_trailing_space(b, ld, line, b->encoding);
				}
			} else { /* Line not split; is there a next one in the paragraph? */
				if ( ld->ld_node.next->next && is_part_of_paragraph((line_desc *)ld->ld_node.next, b->opt.tab_size, &pos, b->encoding) ) {
					ld = (line_desc *)ld->ld_node.next;
					line++;
					done = false;
				}
			}
		}
	} while (!stop && !done);

	end_undo_chain(b);

	if (pa_space) {
		free(pa_space);
		pa_space = NULL;
	}

	if (b->syn) {
		b->attr_len = -1;
		need_attr_update = true;
		update_syntax_states(b, -1, start_line_desc, (line_desc *)ld->ld_node.next);
	}
	update_window_lines(b, b->cur_line_desc, b->cur_y, ne_lines - 2, false);

	goto_line_pos(b, line, pos);
	if (stop || line_down(b) == ERROR) return stop ? STOPPED : ERROR;

	/* Try to find the first non-blank starting with this line. */
	ld = b->cur_line_desc;
	line = b->cur_line;

	do {
		if (ld->line) {
			for (pos = 0; pos < ld->line_len; pos = next_pos(ld->line, pos, b->encoding)) {
				if (!isasciispace(ld->line[pos])) {
					goto_line_pos(b, line, pos);
					return ld->ld_node.next ? OK : ERROR;
				}
			}
		}
		ld = (line_desc *)ld->ld_node.next;
		line++;
	} while (ld->ld_node.next);

	return b->cur_line_desc->ld_node.next ? OK : ERROR;
}
Example #20
0
File: edit.c Project: vigna/ne
int shift(buffer * const b, char *p, char *msg, int msg_size) {
	const bool use_tabs = b->opt.tabs && b->opt.shift_tabs;
	const int64_t init_line = b->cur_line, init_pos = b->cur_pos, init_y = b->cur_y;

	line_desc *ld = NULL, *start_line_desc = NULL;
	int64_t shift_size = 1;
	char dir = '>';
	int shift_mag = b->opt.tab_size, rc = 0;

	/* Parse parm p; looks like [<|>] ### [s|t], but we allow them
	   in any order, once, with optional white space. */
	if (p) {
		int dir_b = 0, size_b = 0, st_b = 0;
		while (*p) {
			if (isasciispace(*p)) p++;
			else if (!dir_b && (dir_b = (*p == '<' || *p == '>'))) dir = *p++;
			else if (!size_b && (size_b = isdigit((unsigned char)*p))) {
				errno = 0;
				shift_size = strtoll(p, &p, 10);
				if (errno) return INVALID_SHIFT_SPECIFIED;
			} else if (!st_b && (st_b = (*p == 's' || *p == 'S'))) {
				shift_mag = 1;
				p++;
			} else if (!st_b && (st_b = (*p == 't' || *p == 'T'))) p++;
			else return INVALID_SHIFT_SPECIFIED;
		}
	}
	shift_size *= max(1, shift_mag);
	if (shift_size == 0) return INVALID_SHIFT_SPECIFIED;

	int64_t first_line = b->cur_line, last_line = b->cur_line, left_col = 0;

	if (b->marking) {
		if (b->mark_is_vertical) left_col = min(calc_width(b->cur_line_desc, b->block_start_pos, b->opt.tab_size, b->encoding),
		                                        calc_width(b->cur_line_desc, b->cur_pos,         b->opt.tab_size, b->encoding));
		first_line = min(b->block_start_line, b->cur_line);
		last_line  = max(b->block_start_line, b->cur_line);
	}

	/* If we're shifting left (dir=='<'), verify that we have sufficient white space
	   to remove on all the relevant lines before making any changes, i. */

	if (dir == '<') {
		shift_size = -shift_size; /* signed shift_size now also indicates direction. */
		for (int64_t line = first_line; !rc && line <= last_line; line++) {
			int64_t pos;
			goto_line(b, line);
			pos = calc_pos(b->cur_line_desc, left_col, b->opt.tab_size, b->encoding);
			while (pos < b->cur_line_desc->line_len &&
			       left_col - calc_width(b->cur_line_desc, pos, b->opt.tab_size, b->encoding) > shift_size) {
				if (isasciispace(b->cur_line_desc->line[pos]))
					pos = next_pos(b->cur_line_desc->line, pos, b->encoding);
				else {
					rc = INSUFFICIENT_WHITESPACE;
					break;
				}
			}
		}
	}


	if (!rc) {
		start_undo_chain(b);
		for (int64_t line = first_line; line <= last_line; line++) {
			int64_t pos, c_pos, c_col_orig, offset;
			b->attr_len = -1;
			goto_line(b, line);
			b->cur_pos = -1;
			ld = b->cur_line_desc;
			if (line == first_line) start_line_desc = ld;
			pos = calc_pos(ld, left_col, b->opt.tab_size, b->encoding);
			/* If left_col is in the middle of a tab, pos will be on that tab. */
			/* whitespace adjustment strategy:
			   1. Starting from left_col, advance to the right to the first non-blank character C.
			   2. Note C's col. The desired new column is this value +/- shift_size.
			   3. Move left looking for the first tab or non-whitespace or the left_col, whichever comes first.
			      Whitespace changes all take place at that transition point.
			   4. While C's col is wrong
			        if C's col is too far to the right,
			          if we're on a space, delete it;
			          else if there's a tab to our left, delete it;
			          else we should not have started, because it's not possible!
			        if C's col is too far to the left,
			           if its needs to be beyond the next tab stop,
			             insert a tab and move right;
			           else insert a space. */
			/* 1. */
			while (pos < ld->line_len && isasciispace(ld->line[pos]))
				pos = next_pos(ld->line, pos, b->encoding);
			if (pos >= ld->line_len) continue; /* We ran off the end of the line. */
			/* line[pos] should be the first non-blank character. */
			/* 2. */
			c_pos = pos;
			c_col_orig = calc_width(ld, c_pos, b->opt.tab_size, b->encoding);
			/* 3. */
			while (pos && ld->line[pos-1] == ' ')
				pos = prev_pos(ld->line, pos, b->encoding);
			/* If pos is non-zero, it should be on a blank, with only blanks between here and c_pos. */
			/* 4. */
			/* offset = how_far_we_have_moved - how_far_we_want_to_move. */
			while (!stop && (offset = calc_width(ld, c_pos, b->opt.tab_size, b->encoding)-c_col_orig - shift_size)) {
				if (offset > 0) { /* still too far right; remove whitespace */
					if (ld->line[pos] == ' ') {
						delete_stream(b, ld, b->cur_line, pos, 1);
						c_pos--;
					}
					else if (pos) { /* should be a tab just to our left */
						pos = prev_pos(ld->line, pos, b->encoding); /* now we're on the tab */
						if (ld->line[pos] == '\t') {
							delete_stream(b, ld, b->cur_line, pos, 1);
							c_pos--;
						}
						else break; /* Should have been a tab. This should never happen! Give up on this line and go mangle the next one. */
					}
					else break; /* This should never happen; give up on this line and go mangle the next one. */
				}
				else if (offset < 0) { /* too far left; insert whitespace */
					char c = ' ';
					if (use_tabs && (b->opt.tab_size - calc_width(ld, pos, b->opt.tab_size, b->encoding) % b->opt.tab_size) <= -offset )
						c = '\t';
					if (insert_one_char(b, ld, b->cur_line, pos, c)) {
						break;
					}
					pos++;
					c_pos++;
				}
			}
		}
		end_undo_chain(b);
		if (b->syn) {
			b->attr_len = -1;
			need_attr_update = true;
			update_syntax_states(b, -1, start_line_desc, (line_desc *)ld->ld_node.next);
		}
		update_window_lines(b, b->top_line_desc, 0, ne_lines - 2, false);
	}

	/* put the screen back where way we found it. */
	goto_line_pos(b, init_line, init_pos);
	delay_update();
	const int64_t avshift = b->cur_y - init_y;
	if (avshift) {
		snprintf(msg, msg_size, "%c%" PRId64, avshift > 0 ? 'T' :'B', avshift > 0 ? avshift : -avshift);
		adjust_view(b, msg);
	}

	return rc;
}
static INLINE void advance_pos(uint32_t *pos, uint32_t n)
{
   khrn_barrier();
   *pos = next_pos(*pos, n);
}
Example #22
0
File: input.c Project: dmt4/ne
char *request(const char *prompt, const char * const default_string, const bool alpha_allowed, const int completion_type, const bool prefer_utf8) {

	set_attr(0);

	input_buffer[pos = len = offset = 0] = 0;
	encoding = ENC_ASCII;
	x = start_x = print_prompt(prompt);

	init_history();

	if (default_string) {
		strncpy(input_buffer, default_string, MAX_INPUT_LINE_LEN);
		len = strlen(input_buffer);
		encoding = detect_encoding(input_buffer, len);
		input_refresh();
	}

	bool first_char_typed = true, last_char_completion = false, selection = false;

	while(true) {

		assert(input_buffer[len] == 0);

		move_cursor(ne_lines - 1, x);

		int c;
		input_class ic;
		do c = get_key_code(); while((ic = CHAR_CLASS(c)) == IGNORE);

		/* ISO 10646 characters *above 256* can be added only to UTF-8 lines, or ASCII lines (making them, of course, UTF-8). */
		if (ic == ALPHA && c > 0xFF && encoding != ENC_ASCII && encoding != ENC_UTF8) ic = INVALID;

		if (ic != TAB) last_char_completion = false;
		if (ic == TAB && !completion_type) ic = ALPHA;

		switch(ic) {

		case INVALID:
			alert();
			break;

		case ALPHA:

			if (first_char_typed) {
				input_buffer[len = 0] = 0;
				clear_to_eol();
			}

			if (encoding == ENC_ASCII && c > 0x7F) encoding = prefer_utf8 || c > 0xFF ? ENC_UTF8 : ENC_8_BIT;
			int c_len = encoding == ENC_UTF8 ? utf8seqlen(c) : 1;
			int c_width = output_width(c);
			assert(c_len > 0);

			if (len <= MAX_INPUT_LINE_LEN - c_len && (alpha_allowed || (c < 0x100 && isxdigit(c)) || c=='X' || c=='x')) {

				memmove(&input_buffer[pos + c_len], &input_buffer[pos], len - pos + 1);

				if (c_len == 1) input_buffer[pos] = c;
				else utf8str(c, &input_buffer[pos]);

				len += c_len;

				move_cursor(ne_lines - 1, x);

				if (x < ne_columns - c_width) {
					if (pos == len - c_len) output_char(c, 0, encoding);
					else if (char_ins_del_ok) insert_char(c, 0, encoding);
					else input_refresh();
				}

				input_move_right(true);
			}
			break;

		case RETURN:
			selection = true;
			break;

		case TAB:
			if (completion_type == COMPLETE_FILE || completion_type == COMPLETE_SYNTAX) {
				bool quoted = false;
				char *prefix, *completion, *p;
				if (len && input_buffer[len - 1] == '"') {
					input_buffer[len - 1] = 0;
					if (prefix = strrchr(input_buffer, '"')) {
						quoted = true;
						prefix++;
					}
					else input_buffer[len - 1] = '"';
				}

				if (!quoted) {
					prefix = strrchr(input_buffer, ' ');
					if (prefix) prefix++;
					else prefix = input_buffer;
				}

				if (last_char_completion || completion_type == COMPLETE_SYNTAX) {
					if (completion_type == COMPLETE_FILE )
						completion = p = request_files(prefix, true);
					else
						completion = p = request_syntax(prefix, true);
					reset_window();
					if (completion) {
						if (*completion) selection = true;
						else completion++;
					}
				}
				else {
					if (completion_type == COMPLETE_FILE )
						completion = p = complete_filename(prefix);
					else
						completion = p = request_syntax(prefix, true);
					last_char_completion = true;
					if (!completion) alert();
				}

				if (completion && (prefix - input_buffer) + strlen(completion) + 1 < MAX_INPUT_LINE_LEN) {
					const encoding_type completion_encoding = detect_encoding(completion, strlen(completion));
					if (encoding == ENC_ASCII || completion_encoding == ENC_ASCII || encoding == completion_encoding) {
						strcpy(prefix, completion);
						if (quoted) strcat(prefix, "\"");
						len = strlen(input_buffer);
						pos = offset = 0;
						x = start_x;
						if (encoding == ENC_ASCII) encoding = completion_encoding;
						input_move_to_eol();
						if (quoted) input_move_left(false);
						input_refresh();
					}
					else alert();
				}
				else if (quoted) strcat(prefix, "\"");

				free(p);
			}
			break;

		case COMMAND:
			if (c < 0) c = -c - 1;
			const int a = parse_command_line(key_binding[c], NULL, NULL, false);
			if (a >= 0) {
				switch(a) {

				case LINEUP_A:
				case LINEDOWN_A:
				case MOVESOF_A:
				case MOVEEOF_A:
				case PAGEUP_A:
				case PAGEDOWN_A:
				case NEXTPAGE_A:
				case PREVPAGE_A:
					if (history_buff) {
						switch(a) {
						case LINEUP_A: line_up(history_buff); break;
						case LINEDOWN_A: line_down(history_buff); break;
						case MOVESOF_A: move_to_sof(history_buff); break;
						case MOVEEOF_A: move_to_bof(history_buff); break;
						case PAGEUP_A:
						case PREVPAGE_A: prev_page(history_buff); break;
						case PAGEDOWN_A:
						case NEXTPAGE_A: next_page(history_buff); break;
						}

						/* In some cases, the default displayed on the command line will be the same as the 
							first history item. In that case we skip it. */

						if (first_char_typed == true 
							 && a == LINEUP_A 
							 && history_buff->cur_line_desc->line 
							 && !strncmp(history_buff->cur_line_desc->line, input_buffer, history_buff->cur_line_desc->line_len))
							line_up(history_buff);

						if (history_buff->cur_line_desc->line) {
							strncpy(input_buffer,
									  history_buff->cur_line_desc->line,
									  min(history_buff->cur_line_desc->line_len,MAX_INPUT_LINE_LEN));
							input_buffer[min(history_buff->cur_line_desc->line_len,MAX_INPUT_LINE_LEN)] = 0;
							len	 = strlen(input_buffer);
							encoding = detect_encoding(input_buffer, len);
						}
						else {
							input_buffer[len = 0] = 0;
							encoding = ENC_ASCII;
						}

						x		= start_x;
						pos	= 0;
						offset = 0;
						input_refresh();
					}
					break;

				case MOVELEFT_A:
					input_move_left(true);
					break;

				case MOVERIGHT_A:
					input_move_right(true);
					break;

				case BACKSPACE_A:
					if (pos == 0) break;
					input_move_left(true);

				case DELETECHAR_A:
					if (len > 0 && pos < len) {
						int c_len = encoding == ENC_UTF8 ? utf8len(input_buffer[pos]) : 1;
						int c_width = get_char_width(&input_buffer[pos], encoding);
						memmove(&input_buffer[pos], &input_buffer[pos + c_len], len - pos - c_len + 1);
						len -= c_len;
						if (input_buffer_is_ascii()) encoding = ENC_ASCII;

						if (char_ins_del_ok) {
							int i, j;

							move_cursor(ne_lines - 1, x);
							delete_chars(c_width);

							for(i = x, j = pos; j < len && i + get_char_width(&input_buffer[j], encoding) < ne_columns - c_width; i += get_char_width(&input_buffer[j], encoding), j = next_pos(input_buffer, j, encoding));

							if (j < len) {
								move_cursor(ne_lines - 1, i);
								while(j < len && i + get_char_width(&input_buffer[j], encoding) < ne_columns) {
									output_char(get_char(&input_buffer[j], encoding), 0, encoding);
									i += get_char_width(&input_buffer[j], encoding);
									j = next_pos(input_buffer, j, encoding);
								}
							}
						}
						else input_refresh();
					}
					break;

				case DELETELINE_A:
					move_cursor(ne_lines - 1, start_x);
					clear_to_eol();
					input_buffer[len = pos = offset = 0] = 0;
					encoding = ENC_ASCII;
					x = start_x;
					break;

				case DELETEEOL_A:
					input_buffer[len = pos] = 0;
					clear_to_eol();
					if (input_buffer_is_ascii()) encoding = ENC_ASCII;
					break;

				case MOVEINCUP_A:
					if (x != start_x) {
						pos = offset;
						x = start_x;
						break;
					}

				case MOVESOL_A:
					input_move_to_sol();
					break;

				case MOVEINCDOWN_A: {
					int i, j;
					for(i = x, j = pos; j < len && i + get_char_width(&input_buffer[j], encoding) < ne_columns; i += get_char_width(&input_buffer[j], encoding), j = next_pos(input_buffer, j, encoding));
					if (j != pos && j < len) {
						pos = j;
						x = i;
						break;
					}
				}

				case MOVEEOL_A:
					input_move_to_eol();
					break;

				case TOGGLESEOL_A:
				case TOGGLESEOF_A:
					if (pos != 0) input_move_to_sol();
					else input_move_to_eol();
					break;

				case PREVWORD_A:
					input_prev_word();
					break;

				case NEXTWORD_A:
					input_next_word();
					break;

				case REFRESH_A:
					input_refresh();
					break;

				case PASTE_A:
					input_paste();
					break;

				case AUTOCOMPLETE_A:
					input_autocomplete();
					break;

				case ESCAPE_A:
					return NULL;

				default:
					break;
				}
			}
			break;

		default:
			break;
		}

		if (selection) {
			const line_desc * const last = (line_desc *)history_buff->line_desc_list.tail_pred->prev;
			assert(input_buffer[len] == 0);
			if (history_buff->num_lines == 0 || len != last->line_len || strncmp(input_buffer, last->line, last->line_len)) add_to_history(input_buffer);
			return input_buffer;
		}

		first_char_typed = false;
	}
}
static void egl_disp_llat_callback(void)
{
   uint32_t flags = vcos_atomic_flags_get_and_clear(&llat_flags);
   khrn_barrier();

   while (flags) {
      uint32_t i;
      DISP_T *disp;

      i = _msb(flags);
      flags &= ~(1 << i);
      disp = disps + i;

      /* do asyncs before we (potentially) provoke another callback */
      if (disp->in_use.asyncs > 0) {
         vcos_assert(disp->in_use.asyncs == 1);
         disp->in_use.asyncs = 0;
         khdispatch_send_async(ASYNC_COMMAND_POST, disp->in_use.pid, disp->in_use.sem);
      }

      /* try to send something to the display */
      if (disp->in_use.want) {
         uint32_t slot;
         khrn_barrier();
         slot = disp->in_use.on & (SLOTS_N - 1);
         if (disp->in_use.slots[slot].swap_interval == 0) {
            uint32_t next_on = next_pos(disp->in_use.on, disp->in_use.n);
            if (next_on != disp->in_use.post) {
               khrn_barrier();
               slot = next_on & (SLOTS_N - 1);
               if (disp->in_use.slots[slot].ready) {
                  khrn_barrier();
               } else {
                  /* next image not ready yet */
                  slot = -1;
               }
            } else {
               /* no more images to display */
               slot = -1;
               if (disp->in_use.finish) {
                  /* master task can continue now... */
                  khrn_barrier();
                  disp->in_use.finish = false;
                  khrn_sync_notify_master();
               }
            }
         } /* else: display current image again */
         if (slot != (uint32_t)-1) {
            EGL_DISP_SLOT_HANDLE_T slot_handle = egl_disp_slot_handle(disp_to_handle(disp), slot);
            bool swap_interval_0 = disp->in_use.slots[slot].swap_interval == 0;
            disp->in_use.want = false;
            if ((vcos_getmicrosecs() - disp->in_use.want_us) > PERMITTED_WANT_RESPONSE_US) {
               khrn_hw_kick();
            }
            if (disp->in_use.slots[slot].skip) {
               vcos_assert(swap_interval_0);
            } else {
               /* todo: what should happen when the window handle changes? */
               disp->in_use.last_win = disp->in_use.slots[slot].win;
               egl_server_platform_display(disp->in_use.slots[slot].win,
                  &disp->in_use.slots[slot].image,
                  (uint32_t)(swap_interval_0 ? EGL_DISP_SLOT_HANDLE_INVALID :
                  slot_handle));
            }
            if (swap_interval_0) {
               egl_disp_callback((uint32_t)slot_handle);
            }
         }
      }
   }
}
Example #24
0
File: input.c Project: dmt4/ne
static void input_move_left(const bool do_refresh) {
	if (pos > 0) {

		const int x_delta = get_char_width(&input_buffer[pos = prev_pos(input_buffer, pos, encoding)], encoding);

		assert(pos >= 0);

		if (x == start_x) {
			offset = pos;

			if (char_ins_del_ok) {
				int i, j;
				for(i = start_x, j = offset; j < len && i + get_char_width(&input_buffer[j], encoding) < ne_columns; i += get_char_width(&input_buffer[j], encoding), j = next_pos(input_buffer, j, encoding));
				if (j < len) {
					move_cursor(ne_lines - 1, i);
					delete_chars(get_char_width(&input_buffer[j], encoding));
				}
				move_cursor(ne_lines - 1, start_x);
				insert_char(get_char(&input_buffer[pos], encoding), 0, encoding);
				move_cursor(ne_lines - 1, start_x);
			}
			else if (do_refresh) input_refresh();
		}
		else x -= x_delta;
	}
}
Example #25
0
File: input.c Project: dmt4/ne
static void input_autocomplete(void) {
	int dx = 0, prefix_pos = pos;
	char *p;

	/* find a usable prefix */
	if (prefix_pos && prefix_pos <= len) {
		prefix_pos = prev_pos(input_buffer, prefix_pos, encoding);
		dx--;
		while (prefix_pos && ne_isword(get_char(&input_buffer[prefix_pos], encoding), encoding)) {
			dx--;
			prefix_pos = prev_pos(input_buffer, prefix_pos, encoding);
		}
		if (! ne_isword(get_char(&input_buffer[prefix_pos], encoding), encoding)) {
			dx++;
			prefix_pos = next_pos(input_buffer, prefix_pos, encoding);
		}
		p = malloc(pos - prefix_pos + 1);
		if (!p) {
			alert(); /* OUT_OF_MEMORY */
			return;
		}
		strncpy(p, &input_buffer[prefix_pos], pos - prefix_pos);
	}
	else p = malloc(1); /* no prefix left of the cursor; we'll give an empty one. */
	p[pos - prefix_pos] = 0;

	int ac_err;
	if (p = autocomplete(p, NULL, true, &ac_err)) {
		encoding_type ac_encoding = detect_encoding(p, strlen(p));
		if (ac_encoding != ENC_ASCII && encoding != ENC_ASCII && ac_encoding != encoding) {
			free(p);
			alert();
		} else {
			encoding = ac_encoding;

			if (prefix_pos < pos) {
				memmove(&input_buffer[prefix_pos], &input_buffer[pos], len - pos + 1);
				len -= pos - prefix_pos;
				pos = prefix_pos;
			}
			int ac_len = strlen(p);
			if (ac_len + len >= MAX_INPUT_LINE_LEN) ac_len = MAX_INPUT_LINE_LEN - len;
			memmove(&input_buffer[pos + ac_len], &input_buffer[pos], len - pos + 1);
			memmove(&input_buffer[pos], p, ac_len);
			len += ac_len;
			while (ac_len > 0) {
				const int cw = get_char_width(&input_buffer[pos],encoding);
				pos = next_pos(input_buffer, pos, encoding);
				ac_len -= cw;
				dx++;
			}
			free(p); 
			x += dx;
			if (x >= ne_columns) {
				dx = x - ne_columns + 1;
				while (dx--) {
					offset = next_pos(input_buffer, offset, encoding);
				}
				x = ne_columns - 1;
			}
		}
	}
	if (ac_err == AUTOCOMPLETE_COMPLETED || ac_err == AUTOCOMPLETE_CANCELLED) {
		do_action(cur_buffer, REFRESH_A, 0, NULL);
		refresh_window(cur_buffer);
		set_attr(0);
		print_prompt(NULL);
	}
	input_refresh();
}
Example #26
0
File: input.c Project: dmt4/ne
static void input_refresh(void) {
	move_cursor(ne_lines - 1, start_x);
	for(int i = start_x, j = offset; j < len; i += get_char_width(&input_buffer[j], encoding), j = next_pos(input_buffer, j, encoding)) {
		if (i + get_char_width(&input_buffer[j], encoding) >= ne_columns) break;
		output_char(get_char(&input_buffer[j], encoding), 0, encoding);
	}
	clear_to_eol();
	fflush(stdout);
}
Example #27
0
File: main.cpp Project: keitee/kb
 void push(T const item)
 {
    head_ = next_pos();
    data_[head_] = item;
    if (size_ < data_.size()) size_++;
 }
Example #28
0
File: main.cpp Project: keitee/kb
 const_iterator end() const
 {
    return const_iterator(*this, next_pos(), true);
 }
Example #29
0
void Snake::tick()
{
  direction mov_dir;
  byte x;
  byte y;
  byte new_sid;

  if (_game_over)
    return;

  if (_food_timer == 0)  // time to spawn food
  {
    _food_x = random(_max_x-2)+1; // don't spawn on border
    _food_y = random(_max_y-2)+1;
  }

  // move head
  next_pos(_dir, &_head_x, &_head_y);

  // Test for hitting edge
  if
    (
      (_head_x == 0)        ||
      (_head_x == _max_x-1) ||
      (_head_y == 0)        ||
      (_head_y == _max_y-1)
    )
  {
    _game_over = true;
    return;
  }

  // Test for eating food
  if (_food_x != 0)
  {
    if ((_head_x == _food_x) &&
        (_head_y == _food_y))
    {
      if (_food_timer == 0)
      {
         // food spawned on the new location of the head... try spawning again next tick
        _food_x = 0;
        _food_y = 0;
      } else
      {
        // Food eaten!
        _food_timer = 0;
        _food_x = 0;
        _food_y = 0;
        if (_snake_len < (SNAKE_ARRAY_SIZE*8)) _snake_len++;
      }
    }
  }

  x = _head_x;
  y = _head_y;

  // Move tail. Well, recalc how each element links to the next
  mov_dir = _dir;
  for (int i=0; i < _snake_len; i++)
  {
    next_pos(mov_dir, &x, &y);

    // Lookout for heading touching tail
    if ((x==_head_x) && (y==_head_y) && (i < _snake_len - 1))
      _game_over = true;

    // Check food just spawned isn't on the snake
    if (x==_food_x && y==_food_y && _food_x > 0 && _food_y > 0 && _food_timer == 0)
    {
      _food_x = 0;
      _food_y = 0;
      _food_timer = 0;
    }

    mov(mov_dir, get_element(i), &mov_dir, &new_sid);
    set_element(i, new_sid);
  }

  if (_food_x!=0)
    _food_timer = 1;
}
Example #30
0
Path
Search::search() {
	expanded = 0;
	Node* cur;
	Path ans(cost_maps[0]);
	make_goal(goal);
	fringe.push(make_start(start));
	double cur_f = -1;
	int iter = 0;
	while (! fringe.is_empty()) {
		iter++;
		cur = fringe.pop();
		cur->set_state(CLOSED);
///		printf("Pop      ");
///		cur->print(stdout);
		if (cur_f - cur->f > 1e-6 ) {
			fprintf(stderr, "f value of node being expanded decreased\n");
			fprintf(stdout, "Node above has f-value lower than previously closed node (%.1lf < %.1lf)\n", cur->f, cur_f);
		}
		cur_f = cur->f;
		expanded++;

		// If we are done, construct the path
		if (cur->check_state(GOAL)) {
			do {
				ans.add_node(Node(cur));
				cur = cur->prev;
			} while (cur != NULL);
			break;
		}

		// Consider neighbours
		Point next_pos(cur->pos);
		while (next_successor(cur->pos, next_pos)) {
			double cost = step_cost(cur->pos, next_pos);
			if (cost >= 0 && cost < HUGE_VAL) {
				double ncost = cur->g + cost;
				Node* next = get_node(next_pos);
				if (next->check_state(CLOSED)) {
					continue;
				} else if (next->check_state(FRINGE)) {
					if (ncost < next->g) {
						// update it
						next->g = ncost;
						next->f = next->g + next->h;
						next->prev = cur;
						fringe.update(next);
					}
				} else {
					next->h = heuristic(next_pos);
					next->g = ncost;
					next->f = next->g + next->h;
					next->prev = cur;
///					printf("Push 0   ");
///					next->print(stdout);
					fringe.push(next);
				}
			}
		}
	}

///	for (int i = 0; i < levels; i++) {
///		printf("level %d:\n", i);
///		printf("Map Costs\n");
///		cost_maps[i]->print(stdout);
///		printf("Path costs\n");
///		path_maps[i]->print(stdout);
///	}
///	ans.print(stdout);

	return ans;
}