Exemple #1
0
Fichier : edit.c Projet : 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;
}
Exemple #2
0
/** @brief Frees a TCP stream **/
inline static void __tcp_free_stream ( pntoh_tcp_session_t session , pntoh_tcp_stream_t *stream , int reason , int extra )
{
	flush_peer_queues ( session , *stream , extra );
	delete_stream ( session , stream , reason , extra );

	return;
}
int delete_sel_stream()
{
  int i;
  for (i = 0; i < nr_cur_stream; i++)
    {
        if (g_apt_streams[i]->selected)
        {
            delete_stream(i);
            i--;
        }
    }

  return 0;

} 
Exemple #4
0
Fichier : buffer.c Projet : dmt4/ne
int delete_one_line(buffer * const b, line_desc * const ld, const int64_t line) {
	assert_line_desc(ld, b->encoding);
	assert_buffer(b);

	block_signals();

	if (ld->line_len && (b->last_deleted = reset_stream(b->last_deleted))) add_to_stream(b->last_deleted, ld->line, ld->line_len);

	/* We delete a line by delete_stream()ing its length plus one. However, if
		we are on the last line of text, there is no terminating line feed. */

	const int error = delete_stream(b, ld, line, 0, ld->line_len + (ld->ld_node.next->next ? 1 : 0));
	release_signals();

	return error;
}
Exemple #5
0
Fichier : search.c Projet : dmt4/ne
int replace(buffer * const b, const int n, const char * const string) {

	int64_t len;

	assert(string != NULL);

	last_replace_empty_match = false;

	len = strlen(string);

	start_undo_chain(b);

	delete_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, n);

	if (len) insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, string, len);

	end_undo_chain(b);

	if (! b->opt.search_back) goto_pos(b, b->cur_pos + len);

	return OK;
}
Exemple #6
0
Fichier : search.c Projet : dmt4/ne
int replace_regexp(buffer * const b, const char * const string) {
	assert(string != NULL);

	bool reg_used = false;
	char *p, *q, *t = NULL;
	if (q = p = str_dup(string)) {

		int len = strlen(p);

		while(true) {
			while(*q && *q != '\\') q++;

			if (!*q) break;

			int i = *(q + 1) - '0';

			if (*(q + 1) == '\\') {
				memmove(q, q + 1, strlen(q + 1) + 1);
				q++;
				len--;
			}
			else if (i >= 0 && i < RE_NREGS && re_reg.start[i] >= 0) {
				if (b->encoding == ENC_UTF8) {
					/* In the UTF-8 case, the replacement group index must be
						mapped through map_group to recover the real group. */
					if ((i = map_group[i]) >= RE_NREGS) {
						free(p);
						return GROUP_NOT_AVAILABLE;
					}
				}
				*q++ = 0;
				*q++ = i;
				reg_used = true;
			}
			else {
				free(p);
				return WRONG_CHAR_AFTER_BACKSLASH;
			}
		}

		if (reg_used) {
			if (t = malloc(re_reg.end[0] - re_reg.start[0] + 1)) {
				memcpy(t, b->cur_line_desc->line + re_reg.start[0], re_reg.end[0] - re_reg.start[0]);
				t[re_reg.end[0] - re_reg.start[0]] = 0;
			}
			else {
				free(p);
				return OUT_OF_MEMORY;
			}
		}

		for(int i = re_reg.num_regs; i-- != 0;) {
			re_reg.end[i] -= re_reg.start[0];
			re_reg.start[i] -= re_reg.start[0];
		}

		start_undo_chain(b);

		delete_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, re_reg.end[0]);

		q = p;
		int64_t pos = 0;

		while(true) {
			if (strlen(q)) {
				insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos + pos, q, strlen(q));
				pos += strlen(q);
			}

			q += strlen(q) + 1;

			if (q - p > len) break;

			assert(*q < RE_NREGS);

			if (re_reg.end[*(unsigned char *)q] - re_reg.start[*(unsigned char *)q]) {

				char c = t[re_reg.end[*(unsigned char *)q]];
				t[re_reg.end[*(unsigned char *)q]] = 0;

				insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos + pos, t + re_reg.start[*(unsigned char *)q], re_reg.end[*(unsigned char *)q] - re_reg.start[*(unsigned char *)q]);

				t[re_reg.end[*(unsigned char *)q]] = c;

				pos += re_reg.end[*(unsigned char *)q] - re_reg.start[*(unsigned char *)q];
			}

			q++;
		}

		end_undo_chain(b);

		if (! b->opt.search_back) goto_pos(b, b->cur_pos + pos);

		free(t);
		free(p);
	}
	else return OUT_OF_MEMORY;

	last_replace_empty_match = re_reg.start[0] == re_reg.end[0];
	return OK;
}
LRESULT CALLBACK stream_WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    RECT		rect ;
    int cxClient, cyClient;
    static HMENU	hMenu ;
    POINT point ;
    int ret, idx;
    TCHAR  buf[64];
    char file_name[MAX_FILE_PATH_LEN];

    static int edit_iItem=-1 ;
    static int edit_iSubItem;

     LVITEM lv_item;
    switch (message)
    {
        case WM_CREATE:
            hwnd_stream= hwnd;
            hMenu = LoadMenu (g_hInstance, TEXT("my_popup_menu")) ;
            hMenu = GetSubMenu (hMenu, 0) ;

            hwnd_dynamic_edit=CreateWindow (TEXT("edit"), TEXT(""),
                WS_CHILD|ES_AUTOHSCROLL,
                CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                hwnd, (HMENU)ID_DYNAMIC_EDIT, g_hInstance, NULL) ;

            SendMessage(hwnd_dynamic_edit, WM_SETFONT, (WPARAM)char_font_2, 0); 

            hwnd_lv = CreateListView(hwnd);
            //InitListViewImageLists(hwnd_lv);
            InitListViewColumns(hwnd_lv);
            lv_row_color_init();
            old_lv_proc = (WNDPROC) SetWindowLong (hwnd_lv, 
                                 	GWL_WNDPROC, (LONG)my_lv_proc) ;

            ShowWindow(hwnd_lv, 1) ;
            refresh_window(hwnd_lv) ;

           add_tip(hwndTip, hwnd_lv, TEXT("点击鼠标右键进行操作"));

            return 0 ;

        case WM_SIZE:
      		cxClient = LOWORD (lParam) ;
      		cyClient = HIWORD (lParam) ;

            MoveWindow(hwnd_lv, 	0, 0,
                cxClient, cyClient, TRUE) ;

            return 0 ;

case WM_NOTIFY:
{

   NMHDR *pt_nmhdr=(void *)lParam;
   switch(LOWORD(wParam))
   { 
     case ID_LV:

     // if code == NM_CLICK - Single click on an item
     if(pt_nmhdr->code == NM_CLICK || pt_nmhdr->code == NM_DBLCLK) 
     {
        int iItem = ((LPNMITEMACTIVATE)lParam)->iItem;
        int iSubItem=((LPNMITEMACTIVATE)lParam)->iSubItem;

        if (iItem>=0 && ((iSubItem>=3 && iSubItem<=5) || iSubItem==7)) 
        {

            ListView_GetSubItemRect(hwnd_lv,iItem,iSubItem,LVIR_LABEL,&rect);
            ListView_GetItemText(hwnd_lv, iItem, iSubItem, buf, sizeof(buf));
            MoveWindow	(hwnd_dynamic_edit
                ,rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
            SetWindowText(hwnd_dynamic_edit, buf);
            ShowWindow (hwnd_dynamic_edit, 1) ;
            SetFocus(hwnd_dynamic_edit);
            SendMessage(hwnd_dynamic_edit, EM_SETSEL, (WPARAM)0, (LPARAM)-1);

            edit_iItem = iItem;
            edit_iSubItem = iSubItem;

        }

            return 0;
     }
    else if (pt_nmhdr->code == NM_RCLICK)
    {
        point = ((LPNMITEMACTIVATE)lParam)->ptAction;
        ListView_GetItem(hwnd_lv, &lv_item);

        ClientToScreen (hwnd_lv, &point) ;
  		TrackPopupMenu (hMenu, TPM_LEFTBUTTON, point.x, point.y, 0, hwnd_stream, NULL) ;
        return 0;

    }
    else if (pt_nmhdr->code == LVN_ITEMCHANGED)
    {
        if (!init_over) break;
        if (lv_in_op)   break;
        //if((((LPNMLISTVIEW)lParam)->uOldState&LVIS_STATEIMAGEMASK) != 
        //    (((LPNMLISTVIEW)lParam)->uNewState&LVIS_STATEIMAGEMASK)) 
        {
            int iItem = ((LPNMITEMACTIVATE)lParam)->iItem;
            int selected = ListView_GetCheckState(hwnd_lv, iItem);

            if (g_apt_streams[iItem]->selected!=selected)
            {
                doc_modified=1;
                g_apt_streams[iItem]->selected=selected;
                update_statusbar();
            }
        }
        return 0;

    }
    
    break;

   }

   break;
}

        case 	WM_COMMAND:
            switch (LOWORD(wParam))
            {
                  
                case    IDM_STREAM_NEW:
                    init_stream(&gt_edit_stream);
                    gt_edit_stream.len=gat_sample_pkts[0].len;
                    memcpy(gt_edit_stream.data, gat_sample_pkts[0].pkt_data, gt_edit_stream.len);

                    ret=DialogBox(g_hInstance, TEXT("STREAM_EDIT_DLG"), hwnd, StreamEditDlgProc);
                    if (IDOK==ret)
                    {
                        add_stream(&gt_edit_stream);
                        re_populate_items();
                    }
               	return 0 ;

                case    IDM_STREAM_NEW_HEX:
                {
                    int len;
                    char buf[MAX_PACKET_LEN];
                    if (get_open_file_name(file_name, hwnd, ALL_FILE_FILTER))
                        return 0;

                    len = read_file_to_buf(buf, sizeof(buf)-1, file_name);
                    if (len>0)
                        add_stream_from_hex_text(buf, len);
                    else
                        err_msg_box("读取文件内容失败");
                   	return 0 ;
                }

                case    IDM_STREAM_NEW_BIN:
                {
                    int len;
                    char buf[MAX_PACKET_LEN];
                    if (get_open_file_name(file_name, hwnd, ALL_FILE_FILTER))
                        return 0;

                    len = read_file_to_buf(buf, sizeof(buf)-1, file_name);
                    if (len>0)
                        add_stream_from_raw_data(buf, len);
                    else
                        err_msg_box("读取文件内容失败");
                   	return 0 ;
                }

                case    IDM_STREAM_NEW_PCAP:
                {
                    if (get_open_file_name(file_name, hwnd, PCAP_FILE_FILTER))
                        return 0;
                    add_stream_from_pcap(file_name);
                   	return 0 ;
                }
                                
                case    IDM_STREAM_DEL:
                    idx=GetIndex(hwnd_lv);
       				//ListView_DeleteItem(hwnd_lv, idx);
                    delete_stream(idx);
                    re_populate_items();
                    update_statusbar();
       				return 0 ;
                case    IDM_STREAM_EDIT:
                    cur_strm_idx=GetIndex(hwnd_lv);
                    if (cur_strm_idx<0) return 0;
                    cpy_stream(&gt_edit_stream, g_apt_streams[cur_strm_idx]);
                    ret=DialogBox(g_hInstance, TEXT("STREAM_EDIT_DLG"), hwnd, StreamEditDlgProc);
                    if (IDOK==ret)
                    {
                        doc_modified=1;
                        cpy_stream(g_apt_streams[cur_strm_idx], &gt_edit_stream);
                        re_populate_items();
                    }
       				//ListView_DeleteAllItems(hwnd_lv);
       				return 0 ;
                case    IDM_STREAM_DEL_SEL:
       				//DelSel(hwnd_lv);
                    delete_sel_stream();
                    re_populate_items();
                    update_statusbar();
       				return 0 ;

                case    IDM_STREAM_SEL_ALL:
       				SelAll(hwnd_lv);
       				return 0 ;

                case    IDM_STREAM_SEL_RVS:
       				SelRvs(hwnd_lv);
       				return 0 ;
                    
                case    IDM_STREAM_COPY:
       				copy_idx = GetIndex(hwnd_lv);
       				return 0 ;

                case    IDM_STREAM_PASTE:
       				cpy_stream(&gt_edit_stream, g_apt_streams[copy_idx]);
                    add_stream(&gt_edit_stream);
                    re_populate_items();
       				return 0 ;

                case    IDM_STREAM_MAKE_FRAGS:
                {
       				ret=DialogBox(g_hInstance, TEXT("FRAG_DLG"), hwnd, FragDlgProc);
       				return 0 ;
                }

                case    IDM_STREAM_SEL2PCAP:
                {
                    ret=get_save_file_name(file_name, hwnd, PCAP_FILE_FILTER, PCAP_FILE_SUFFIX);
                    if (ret) return 0 ;

       				stream2dump(file_name);
                    update_pcap_file_history(file_name);
       				return 0 ;
                }

                case    IDM_STREAM_2_BIN:
                {
                    ret=get_save_file_name(file_name, hwnd, BIN_FILE_FILTER, BIN_FILE_SUFFIX);
                    if (ret) return 0 ;

       				stream_2_bin(file_name);
       				return 0 ;
                }

                case    IDM_STREAM_2_TEXT:
                {
                    ret=get_save_file_name(file_name, hwnd, TEXT_FILE_FILTER, TEXT_FILE_SUFFIX);
                    if (ret) return 0 ;

       				stream_2_text(file_name);
       				return 0 ;
                }
                
                case    ID_DYNAMIC_EDIT:
       				if (HIWORD(wParam)==EN_KILLFOCUS)
                    {

            update_grid_from_edit(edit_iItem, edit_iSubItem);
            edit_iItem=-1;

           				return 0 ;
                    }

            }
            break;

case   WM_KEYDOWN:
    if (VK_RETURN==wParam)
    {

        SetFocus(hwnd);

         return 0;

    }
    break;

        case 	WM_INITMENUPOPUP:
        {
            int idx=GetIndex(hwnd_lv);
            t_stream *pt_stream = g_apt_streams[idx];
            int sel_cnt=GetSelCnt(hwnd_lv);
            int item_cnt=ListView_GetItemCount(hwnd_lv);
            if (lParam == 0)
            {
                UINT add_stream_menu_state = nr_cur_stream<MAX_STREAM_NUM ? MF_ENABLED : MF_GRAYED;
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_NEW, add_stream_menu_state);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_NEW_HEX, add_stream_menu_state);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_NEW_BIN, add_stream_menu_state);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_NEW_PCAP, add_stream_menu_state);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_EDIT, idx>=0 ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_DEL, idx>=0 ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_COPY, idx>=0 ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_PASTE, copy_idx>=0 && item_cnt>copy_idx ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_DEL_SEL, sel_cnt ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_SEL_ALL, item_cnt ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_SEL_RVS, item_cnt ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_MAKE_FRAGS, idx>=0&&stream_fragable(pt_stream) ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_SEL2PCAP, sel_cnt ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_2_BIN, idx>=0 ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem ((HMENU) wParam, IDM_STREAM_2_TEXT, idx>=0 ? MF_ENABLED : MF_GRAYED);

                return 0;

            }

            break;
        }

    }
    
    return DefWindowProc (hwnd, message, wParam, lParam) ;
}
Exemple #8
0
/** @brief API for add an incoming segment **/
int ntoh_tcp_add_segment ( pntoh_tcp_session_t session , pntoh_tcp_stream_t stream , struct ip *ip , size_t len , void *udata )
{
	size_t				iphdr_len = 0;
	size_t				tcphdr_len = 0;
	size_t				payload_len = 0;
	struct tcphdr			*tcp = 0;
	pntoh_tcp_peer_t		origin = 0;
	pntoh_tcp_peer_t		destination = 0;
	unsigned int			tstamp = 0;
	int				ret = NTOH_OK;
	pntoh_tcp_segment_t		segment = 0;
    int who;

	if ( !stream || !session )
		return NTOH_ERROR_PARAMS;

	/* verify IP header */
	if ( !ip ) // no ip header
		return NTOH_INCORRECT_IPHEADER;

	if ( len <= sizeof(struct ip) ) // no data
		return NTOH_INCORRECT_LENGTH;

	if ( ( iphdr_len = 4 * ( ip->ip_hl ) ) < sizeof(struct ip) ) // incorrect ip header length
		return NTOH_INCORRECT_IP_HEADER_LENGTH;

	if ( len < ntohs( ip->ip_len ) ) // incorrect capture length
		return NTOH_NO_ENOUGH_DATA;

	if ( ip->ip_v != 4 ) // only handle IPv4
		return NTOH_NOT_IPV4;

	/* check IP addresses */
	if ( !(
			( stream->client.addr == ip->ip_src.s_addr && stream->server.addr == ip->ip_dst.s_addr ) ||
			( stream->client.addr == ip->ip_dst.s_addr && stream->server.addr == ip->ip_src.s_addr )
		))
		return NTOH_IP_ADDRESSES_MISMATCH;

	if ( ip->ip_p != IPPROTO_TCP )
		return NTOH_NOT_TCP;

	tcp = (struct tcphdr*) ( (unsigned char*)ip + iphdr_len );

	/* check TCP header */
    if ( ( tcphdr_len = tcp->th_off * 4 ) < sizeof(struct tcphdr) )
            return NTOH_INCORRECT_TCP_HEADER_LENGTH;

	if ( !tcp->th_flags || tcp->th_flags == 0xFF )
		return NTOH_INVALID_FLAGS;

	lock_access ( &stream->lock );

    /* check TCP ports */
    if ( !(
    		( tcp->th_dport == stream->tuple.dport && tcp->th_sport == stream->tuple.sport ) ||
    		( tcp->th_dport == stream->tuple.sport && tcp->th_sport == stream->tuple.dport )
    	))
    	return NTOH_TCP_PORTS_MISMATCH;

    payload_len = ntohs(ip->ip_len) - iphdr_len - tcphdr_len;

    /* get origin and destination */
    if ( stream->tuple.source == ip->ip_src.s_addr )
    {
    	origin = &stream->client;
    	destination = &stream->server;
        who = NTOH_SENT_BY_CLIENT;
    }else{
    	origin = &stream->server;
    	destination = &stream->client;
        who = NTOH_SENT_BY_SERVER;
    }

    get_timestamp ( tcp , tcphdr_len , &tstamp );

    /* PAWS check */
    if ( tstamp > 0 && origin->lastts > 0 )
    {
    	if ( tstamp < origin->lastts )
    	{
    		ret = NTOH_PAWS_FAILED;
    		goto exitp;
    	}

        if ( ntohl(tcp->th_seq) <= origin->next_seq )
        	origin->lastts = tstamp;

    }else if ( tstamp > 0 && !(origin->lastts) )
    	origin->lastts = tstamp;

    if ( origin->next_seq > 0 && (origin->isn - ntohl ( tcp->th_seq ) ) < origin->next_seq )
    {
    	ret = NTOH_TOO_LOW_SEQ_NUMBER;
    	goto exitp;
    }

    if ( destination->next_seq > 0 && (origin->ian - ntohl(tcp->th_ack) ) < destination->next_seq )
    {
    	ret = NTOH_TOO_LOW_ACK_NUMBER;
    	goto exitp;
    }

    /* @todo some TCP/IP stacks implementations overloads the MSS on certain segments */
    /*if ( origin->mss > 0 && payload_len > origin->mss )
    	return NTOH_SEGMENT_EXCEEDS_MSS;*/

    /* switch between connection status */
    switch ( stream->status )
    {
    	case NTOH_STATUS_CLOSED:
    	case NTOH_STATUS_SYNSENT:
    	case NTOH_STATUS_SYNRCV:
    		if ( payload_len > 0 )
    		{
    			ret = NTOH_HANDSHAKE_FAILED;
    			goto exitp;
    		}

    		ret = handle_new_connection ( stream , tcp , origin ,  destination , udata );
    		if ( ret == NTOH_OK )
    		{
    			if ( origin->receive )
    			{
    				if ( stream->status == NTOH_STATUS_ESTABLISHED )
    					((pntoh_tcp_callback_t)stream->function) ( stream , origin , destination , 0 , NTOH_REASON_SYNC , NTOH_REASON_ESTABLISHED );
    				else
    					((pntoh_tcp_callback_t)stream->function) ( stream , origin , destination , 0 , NTOH_REASON_SYNC , NTOH_REASON_SYNC );
    			}
    		}else{
    			lock_access ( &session->lock );
    			delete_stream ( session , &stream , NTOH_REASON_SYNC , ret );
    			unlock_access ( &session->lock );
    		}

    		break;

    	case NTOH_STATUS_ESTABLISHED:
    		ret = handle_established_connection ( session , stream , tcp , payload_len , origin , destination , udata, who );
    		break;

    	default:
    		segment = new_segment( ntohl ( tcp->th_seq ) - origin->isn , ntohl ( tcp->th_ack ) - origin->ian , payload_len , tcp->th_flags , udata );
    		handle_closing_connection ( session , stream , origin , destination , segment, who );

    		if ( stream->status == NTOH_STATUS_CLOSED )
    		{
    			lock_access ( &session->lock );
    			__tcp_free_stream ( session , &stream , NTOH_REASON_SYNC , NTOH_REASON_CLOSED );
    			unlock_access ( &session->lock );
    			stream = 0;
    		}
    		break;
    }

	if ( ret == NTOH_OK )
	{
		if ( stream != 0 )
			gettimeofday ( & (stream->last_activ) , 0 );

		if ( payload_len == 0 )
			ret = NTOH_SYNCHRONIZING;
	}

exitp:
	if ( stream != 0 )
		unlock_access ( &stream->lock );

	return ret;
}
Exemple #9
0
Fichier : buffer.c Projet : dmt4/ne
void delete_to_eol(buffer * const b, line_desc * const ld, const int64_t line, const int64_t pos) {

	if (!ld || pos >= ld->line_len) return;
	delete_stream(b, ld, line, pos, ld->line_len - pos);
}
Exemple #10
0
Fichier : edit.c Projet : 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;
}
Exemple #11
0
Fichier : edit.c Projet : 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;
}
Exemple #12
0
Fichier : edit.c Projet : vigna/ne
static void trim_trailing_space(buffer * const b, line_desc *ld, const int64_t line, const encoding_type encoding) {
	if (!ld->line) return;
	int64_t pos = ld->line_len;
	while (pos > 0 && isasciispace(ld->line[pos - 1])) pos = prev_pos(ld->line, pos, encoding);
	if (pos >= 0 && pos < ld->line_len) delete_stream(b, ld, line, pos, ld->line_len - pos);
}
Exemple #13
0
Fichier : edit.c Projet : vigna/ne
static int to_something(buffer *b, int (to_first)(int), int (to_rest)(int)) {
	assert_buffer(b);

	/* If we are after the end of the line, just return ERROR. */

	if (b->cur_line == b->num_lines -1 && b->cur_pos >= b->cur_line_desc->line_len) return ERROR;

	int64_t pos = b->cur_pos;
	int c;
	/* First of all, we search for the word start, if we're not over it. */
	if (pos >= b->cur_line_desc->line_len || !ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding))
		if (search_word(b, 1) != OK)
			return ERROR;

	bool changed = false;
	int64_t new_len = 0;
	pos = b->cur_pos;
	const int64_t cur_char = b->cur_char;
	const int cur_x = b->cur_x;
	/* Then, we compute the word position extremes, length of the result (which
		may change because of casing). */
	while (pos < b->cur_line_desc->line_len && ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) {
		const int new_c = new_len ? to_rest(c) : to_first(c);
		changed |= (c != new_c);

		if (b->encoding == ENC_UTF8) new_len += utf8seqlen(new_c);
		else new_len++;

		pos = next_pos(b->cur_line_desc->line, pos, b->encoding);
	}

	const int64_t len = pos - b->cur_pos;
	if (!len) {
		char_right(b);
		return OK;
	}

	if (changed) {
		/* We actually perform changes only if some character was case folded. */
		char * word = malloc(new_len * sizeof *word);
		if (!word) return OUT_OF_MEMORY;

		pos = b->cur_pos;
		new_len = 0;
		/* Second pass: we actually build the transformed word. */
		while (pos < b->cur_line_desc->line_len && ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) {
			if (b->encoding == ENC_UTF8) new_len += utf8str(new_len ? to_rest(c) : to_first(c), word + new_len);
			else {
				word[new_len] = new_len ? to_rest(c) : to_first(c);
				new_len++;
			}

			pos = next_pos(b->cur_line_desc->line, pos, b->encoding);
		}

		start_undo_chain(b);

		delete_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, len);
		if (new_len) insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, word, new_len);

		free(word);

		end_undo_chain(b);

		if (cur_char < b->attr_len) b->attr_len = cur_char;
		update_line(b, b->cur_line_desc, b->cur_y, cur_x, false);
		need_attr_update = true;
	}

	return search_word(b, 1);
}