home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
-
- MODUL
- block.c
-
- DESCRIPTION
- In this module are all functions that work with blocks.
-
- NOTES
- - A block has these attributes:
- 1- the editor it is in
- 2- the type (BT_NONE, BT_LINE, BT_NORMAL or BT_VERTICAL)
- if it is BT_NONE, there is no block.
- 3- a start-position (line/column). If the type is not BT_NONE,
- this field is guranteed to contain a valid position.
- 4- an end-position. If the line is -1, the end-position is not
- yet defined.
-
- ******************************************************************************/
-
- /**************************************
- Includes
- **************************************/
- #include <defs.h>
- #include "clipboard.h"
- #define MYDEBUG 1
- #include "debug.h"
-
-
- /**************************************
- Globale Variable
- **************************************/
- Prototype UWORD is_inblock (Line, Column);
- Prototype void displayblock (BOOL);
- Prototype void redraw_block (BOOL, Line, Column, Line, Column);
- Prototype void do_blocktype (void);
- Prototype void do_block (void);
- Prototype BOOL block_ok (void);
- Prototype void do_copy (void);
- Prototype char * block_to_string (void);
- Prototype void do_bdelete (void);
- Prototype void do_bcopy (void);
- Prototype void do_bmove (void);
- Prototype void do_bsource (void);
-
-
- /**************************************
- Interne Defines & Strukturen
- **************************************/
- #define SWAP(a,b) (void)((a)^=(b),(b)^=(a),(a)^=(b))
- #define MIN(a,b) ((a) <= (b) ? (a) : (b))
- #define MAX(a,b) ((a) >= (b) ? (a) : (b))
-
- #define BF_LINESWAP 1L
- #define BF_COLUMNSWAP 2L
-
-
- /**************************************
- Interne Variable
- **************************************/
- static UWORD block_type = BT_LINE; /* default-type of block */
-
-
- /**************************************
- Interne Prototypes
- **************************************/
-
-
- /*****************************************************************************
-
- NAME
- is_inblock
-
- PARAMETER
- Line line; The line we want to check
- Column column; the column we are in. If column == -1,
- we just check the line.
-
- RETURN
- UWORD blockpos; Flags:
-
- BP_OUTSIDE we are not inside any block.
- BP_START we are in the line where the block starts.
- BP_END we are in the line where the block ends.
- BP_INSIDE we are really inside the block.
-
- DESCRIPTION
- This function checks whether a position is inside a block.
- If it isn't, we get BP_OUTSIDE (= 0). In the other case, we
- have several flags. If line is the start-line of the block,
- BP_START is set. The same goes for the end-line.
- Normal and vertical blocks also check for the column.
- If we don't care for this, we may simply specify -1L for the
- column. Else, we give the column we want to check and get an
- additional BP_INSIDE if we are really inside the block.
-
- EXAMPLE
-
- BP_OUTSIDE there is no block in that line
-
- BP_START the line is the start-line of the block. Also the
- block has more than one line since BP_END is not
- set. The block is not a line-block (BP_INSIDE is
- always true for line-blocks !).
-
- BP_START|BP_END The block has only one line and we are in it. This is
- also no line-block.
-
- BP_START|BP_INSIDE We are inside the block and on it's start-line.
-
- BP_INSIDE this position is inside the block, but not in the
- start- nor in the end-line.
-
- ******************************************************************************/
-
- UWORD is_inblock (Line line, Column col)
- {
- UWORD blockpos = BP_OUTSIDE;
-
- /* Look if there is a block, the actual editor is the one that
- has it, we are not in a commandline and the line is inside it.
- NOTE: if there is no end-line yet, the last condition can never
- be TRUE ! */
-
- if ( ActualBlock.type != BT_NONE &&
- Ep == ActualBlock.ep &&
- !globalflags.Comlinemode &&
- line >= ActualBlock.start_line &&
- line <= ActualBlock.end_line )
- {
-
- /* Check for start- and end-line */
-
- if (line == ActualBlock.start_line)
- blockpos |= BP_START;
-
- if (line == ActualBlock.end_line)
- blockpos |= BP_END;
-
- /* now check, if we are inside the block */
-
- switch (ActualBlock.type)
- {
- case BT_LINE:
- /* in a line-block, we are always inside */
- blockpos |= BP_INSIDE;
- break;
-
- case BT_NORMAL:
- {
- BOOL after_start, before_end;
-
- /* in a normal block, we must also check the column.
- In the startline, we are inside the block if we are to the
- left of the startcolumn. In the endline, we must be to
- the right. */
- /* NOTE that we check the lines above ! */
-
- if (line > ActualBlock.start_line ||
- (col == -1 || col >= ActualBlock.start_column)
- )
- after_start = TRUE;
- else
- after_start = FALSE;
-
- if (line < ActualBlock.end_line ||
- (col == -1 || col <= ActualBlock.end_column ||
- ActualBlock.end_column == (LINELEN(Ep,line)) )
- )
- before_end = TRUE;
- else
- before_end = FALSE;
-
- if (after_start && before_end)
- blockpos |= BP_INSIDE;
- }
- break;
-
- case BT_VERTICAL:
- /* in a vertical block, we must be between the start- and the
- end-column */
-
- if (( col == -1 ||
- ( col >= ActualBlock.start_column &&
- col <= ActualBlock.end_column ) ) &&
- line >= ActualBlock.start_line &&
- line <= ActualBlock.end_line )
- blockpos |= BP_INSIDE;
- break;
- } /* switch (ActualBlock.type) */
- } /* if validblock */
-
- /* return the flags */
-
- return (blockpos);
- } /* is_inblock */
-
-
- /*****************************************************************************
-
- NAME
- displayblock
-
- PARAMETER
- BOOL on; Shall we turn the block on ?
-
- RETURN
- void
-
- DESCRIPTION
- This function displays the block. If on is TRUE, the block
- is drawn (again), else we turn the block off. In this case, the
- block-selection is lost !
-
- ******************************************************************************/
-
- void displayblock (BOOL on)
- {
- if (on)
- {
- /* draw block and write the text over it */
- redraw_block (TRUE,
- Ep->topline, Ep->topcolumn,
- Ep->topline + Lines - 1, Ep->topcolumn + Columns - 1);
-
- } else if (block_ok ()) /* turn block off AND there was a block */
- {
- ED * ep = Ep;
- RP * rp = ep->win->RPort;
- UWORD start;
- UWORD end;
-
- /* no block anymore */
-
- ActualBlock.type = BT_NONE;
- ActualBlock.ep = NULL;
-
- /* block is not visible */
- if (ActualBlock.end_line < ep->topline)
- return;
-
- /* start-line: If block starts above the 1st visible line,
- we start in line 0 else in the line where the block starts. */
-
- if (ActualBlock.start_line < ep->topline)
- start = ep->topline;
- else
- start = ActualBlock.start_line;
-
- /* is end-line visible ? */
- if (ep->topline + Lines > ActualBlock.end_line)
- end = ActualBlock.end_line;
- else
- /* only upto the end of the display */
- end = ep->topline + Lines -1;
-
- if (start <= end)
- {
- /* color and mask */
-
- SetAPen (rp, TEXT_BPEN);
- SetWrMsk (rp, BLOCK_MASK);
-
- /* clear area */
- RectFill (rp, Xbase, ROW(start - Ep->topline), Xpixs,
- ROW(end-Ep->topline + 1)-1);
-
- /* redraw text */
- redraw_block (TRUE, start, ep->topcolumn,
- end, ep->topcolumn + Columns -1);
- }
- } else /* just say "there is no block" */
- ActualBlock.type = BT_NONE;
-
- } /* displayblock */
-
-
- /*****************************************************************************
-
- NAME
- do_blocktype
-
- PARAMETER
- av[0] : blocktype
- av[1] : LINE/CHARACTER/NORMAL/VERTICAL
-
- RETURN
- void
-
- DESCRIPTION
- This sets the type of block you want to use. Allowed are 3 types
- of blocks:
-
- LINE: The line-block begins in a line and ends in a line.
- The columns are ignored and both lines are included
- in the block.
- CHARCTER or NORMAL: The character-block begins at a specifiy line
- and columns and ends at another character-position.
- VERTICAL: The vertical block is a rectangular region of text
- like a column of a table.
-
- If you have already marked a block, it is converted to the new type.
-
- ******************************************************************************/
-
- void do_blocktype (void)
- {
- switch (av[1][0])
- {
- case 'l':
- case 'L':
- block_type = BT_LINE;
- break;
-
- case 'c':
- case 'C':
- case 'n':
- case 'N':
- block_type = BT_NORMAL;
- break;
-
- case 'v':
- case 'V':
- block_type = BT_VERTICAL;
- break;
- }
-
- /* check if there is a block and convert the type */
- if (block_ok() && ActualBlock.type != block_type)
- {
- /* set new type */
- ActualBlock.type = block_type;
-
- if (block_type == BT_NORMAL)
- {
- int linelen;
-
- /* check start and end-columns */
- linelen = LINELEN(Ep,ActualBlock.start_line);
-
- if (linelen < ActualBlock.start_column)
- ActualBlock.start_column = linelen;
-
- linelen = LINELEN(Ep,ActualBlock.end_line);
-
- if (linelen < ActualBlock.end_column)
- ActualBlock.end_column = linelen;
- }
-
- /* clean screen and force redraw */
- text_redisplay ();
- }
- } /* do_blocktype */
-
-
- /*****************************************************************************
-
- NAME
- do_block
-
- PARAMETER
- av[0] : block unblock bstart bend lineblock
-
- RETURN
- void
-
- DESCRIPTION
- This routine allows to specify the limits of a block.
-
- The two commands BSTART and BEND can be used anywhere in the
- text (ie. you can user BEND above a BSTART). In this case,
- BEND and BSTART swap their meanings, ie. BEND now sets the start
- of the block and BSTART the end. This is for specifying a block
- with the mouse. If you drag the mouse above the BSTART, the BEND
- will begin to set the beginning of the block and if you drag it
- down over the end of the block, BEND will switch back.
-
- ******************************************************************************/
-
- void do_block (void)
- {
- ED * ep = Ep;
-
- /* make sure we work on the most recent version of the text */
-
- text_sync ();
-
- /* look for the 1st character */
-
- switch(av[0][0])
- {
- case 'b': /* Block Bstart Bend */
- switch (av[0][1]) /* b[lse] */
- {
- case 'l': /* BLock */
- /* if there is no block yet, we set the start-line */
-
- if (ActualBlock.type == BT_NONE)
- {
- bstart:
- /* set the editor, the start-line and the type. To
- make clear the end-line is not valid yet, we set
- it to -1 */
-
- ActualBlock.ep = ep;
- ActualBlock.type = block_type;
- ActualBlock.start_line = ep->line;
- ActualBlock.start_column = ep->column;
- ActualBlock.end_line = -1;
- ActualBlock.flags = 0;
-
- title ("Block begin");
- } else
- {
- /* if there is a block */
-
- if (block_ok ())
- {
- /* shall we automagically unblock ? */
-
- if (ep->config.autounblock)
- {
- /* trun block off */
-
- text_redrawblock (0);
-
- /* set start */
-
- goto bstart;
- } else
- {
- /* no auto-unblock ? ERROR ! */
-
- error ("block:\nBlock already marked");
-
- break;
- } /* autounblock */
- } /* if there is already a block */
-
- /* The last BLOCK began in another editor: Restart ! */
-
- if (ActualBlock.ep != ep)
- goto bstart;
-
- ActualBlock.end_line = ep->line;
- ActualBlock.end_column = ep->column;
-
- /* now, the block is ready ! */
-
- title ("Block end");
-
- text_redrawblock (1); /* Now display */
- }
- break;
-
- case 's': /* BStart */
- /* no block yet or the old block was in another editor ? */
- if (ActualBlock.type == BT_NONE || ActualBlock.ep != ep)
- {
- /* is there an old block and the editor that contains
- the block is not iconified */
- if (ActualBlock.type != BT_NONE &&
- !ActualBlock.ep->iconmode)
- {
- /* change editor */
- switch_ed (ActualBlock.ep);
-
- /* switch block off */
- text_redrawblock (0);
-
- /* come back */
- switch_ed (ep);
- }
-
- goto bstart;
- }
-
- if (ActualBlock.end_line != -1)
- {
- redraw_block (FALSE,
- ep->line,
- ep->column,
- -1, -1);
- } else
- {
- ActualBlock.start_line = ep->line;
- ActualBlock.start_column = ep->column;
-
- title ("Block begin");
- }
- break;
-
- case 'e': /* bend */
- /* It is not possible to use BEND if there is no
- start yet or the block is in another editor */
-
- if (ActualBlock.type == BT_NONE)
- {
- error ("bend:\n You must use BLOCK or\nBSTART first");
- break;
- } else if (ActualBlock.ep != ep)
- {
- error ("bend:\nYou cannot set the end for\n"
- "a block in another editor !");
- break;
- }
-
- /* say what we do */
- title ("Block end");
-
- /* if there was no end yet, just set it and force
- a redisplay */
-
- if (ActualBlock.end_line == -1)
- {
- ActualBlock.end_line = ep->line;
- ActualBlock.end_column = ep->column;
-
- text_redrawblock (1); /* Now display */
- } else
- {
- redraw_block (FALSE,
- -1, -1,
- ep->line, ep->column);
- }
- break;
- }
- break;
-
- case 'u':
- /* force UNDRAW and say what we did */
-
- text_redrawblock (0);
-
- title ("Block unmarked");
- break;
-
- case 'l':
- /* mark the whole line as a block */
-
- ActualBlock.ep = ep;
- ActualBlock.type = BT_NORMAL;
- ActualBlock.start_line =
- ActualBlock.end_line = ep->line;
- ActualBlock.start_column = 0;
- ActualBlock.end_column = Clen;
- ActualBlock.flags = 0;
-
- title ("Line marked");
-
- /* force redraw */
-
- text_redrawblock (1);
- break;
- }
- } /* do_block */
-
-
- /*****************************************************************************
-
- NAME
- block_ok
-
- PARAMETER
- void
-
- RETURN
- BOOL
-
- DESCRIPTION
- Returns TRUE, if there is a valid block.
-
- ******************************************************************************/
-
- BOOL block_ok (void)
- {
- /* A block is valid, if it has a type and a valid end-line */
-
- return ((BOOL)(ActualBlock.type != BT_NONE && ActualBlock.end_line >= 0));
- } /* block_ok */
-
-
- void test (void)
- {
- } /* test */
-
-
- /*****************************************************************************
-
- NAME
- block_to_string
-
- PARAMETER
- void
-
- RETURN
- char * string;
-
- DESCRIPTION
- Creates a string from the currently marked block. The lines
- are separated with '\n' and the string is terminated with
- '\0'.
-
- NOTES
- - The string will only contain '\n's, if the end of a line is
- included in the block.
- - The block has to be freed with free() if you don't need it anymore,
- but this may change.
-
- HISTORY
- 13. Feb 1993 ada created
-
- ******************************************************************************/
-
- void do_copy (void)
- {
- struct IOClipReq * ior;
- char * str = block_to_string ();
-
- if (str)
- {
- D(bug("block_to_string:\n`%s'\n", str));
-
- if (ior = CBOpen (0))
- {
- CBWriteFTXT (ior, str);
-
- CBClose (ior);
- }
-
- free (str);
- }
- else
- D(bug("block_to_string: (NUL)\n"));
- } /* do_copy */
-
-
- char * block_to_string (void)
- {
- ED * ep;
- Line line;
- int length;
- int linelen;
- char * string,
- * ptr,
- * text;
-
- if (block_ok ())
- {
- ep = ActualBlock.ep;
-
- /* to prevent us from write the same code twice (once for
- figuring out how long the string will be and once for actually
- filling the string), we simply check if "string" is NULL.
- If it is, we have to get the length else we copy the contents. */
-
- ptr = string = NULL;
-
- /*
- LINE: The length of the block is the sum of the lengths of all
- lines + CR + \0.
-
- NORMAL: The length of this block is the sum of the lengths of all
- body lines plus the length of the start- and the end-line
- plus \0. The length of the start-line is
-
- o 1, if length < start_column
- o length-start_column+1, if length > start_column
-
- and the length of the end-line is
-
- o end_column+1, if length > end_column
- o length+1, if length < end_column
-
- If the block has only one line, the length is
-
- o end_column-start_column if length > end_col
- o length-start_column+1 if length < end_col
-
- VERTICAL: The length of the block is the sum of the lengths of
- all lines + CR + \0. The length of a line is
-
- o 0 if the line is < start-column
- o length-start_column if the line is < end-column
- o start_column-end_column if line is >= end-column
-
- When we have the length, we allocate memory for it and copy
- the block into that memory.
- */
-
- length = 1; /* ending '\0' */
-
- text_sync (); /* use latest text */
-
- do {
- for (line=ActualBlock.start_line; line <= ActualBlock.end_line;
- line ++)
- {
- text = GETTEXT (ep,line);
- linelen = strlen (text);
-
- if (linelen > 256)
- {
- D(bug("block_to_string: Aborting..."
- "len (%ld) in line %ld too large !\n",
- linelen, line));
- break;
- }
-
- if (string && ptr-string > length)
- break;
-
- switch (ActualBlock.type)
- {
- case BT_LINE:
- {
- if (string)
- {
- strcpy (ptr, text);
- ptr += linelen;
-
- *ptr ++ = '\n'; /* always add LF */
- }
- else
- length += linelen + 1;
- }
- break;
-
- case BT_NORMAL:
- if (line != ActualBlock.start_line)
- {
- if (line != ActualBlock.end_line)
- {
- /* body line */
-
- if (string)
- {
- strcpy (ptr, text);
- ptr += linelen;
-
- *ptr ++ = '\n'; /* always add LF */
- }
- else
- length += linelen + 1;
- }
- else
- {
- /* end-line */
- if (string)
- {
- strncpy (ptr, text, ActualBlock.end_column);
- ptr += ActualBlock.end_column;
- }
- else
- length += ActualBlock.end_column;
-
- if (linelen == ActualBlock.end_column)
- {
- if (string)
- *ptr ++ = '\n';
- else
- length ++;
- }
- }
- }
- else if (line != ActualBlock.end_line)
- {
- /* start-line */
- if (linelen > ActualBlock.start_column)
- {
- if (string)
- {
- strcpy (ptr, text + ActualBlock.start_column);
- ptr += strlen (ptr);
- }
- else
- length += linelen - ActualBlock.start_column;
- }
-
- if (string)
- *ptr ++ = '\n';
- else
- length ++;
- }
- else /* block has only one line */
- {
- if (linelen > ActualBlock.end_column)
- {
- /* copy part of the line */
-
- linelen = ActualBlock.end_column -
- ActualBlock.start_column + 1;
-
- if (string)
- {
- strncpy (ptr, text + ActualBlock.start_column,
- linelen);
- ptr += linelen;
- }
- else
- length += linelen;
- }
- else if (linelen > ActualBlock.start_column)
- {
- /* end of line + CR */
- if (string)
- {
- strcpy (ptr, text + ActualBlock.start_column);
- ptr += strlen (ptr);
-
- *ptr ++ = '\n';
- }
- else
- {
- linelen -= ActualBlock.start_column;
-
- length += linelen + 1;
- }
- }
- else
- {
- /* only CR */
-
- if (string)
- *ptr ++ = '\n';
- else
- length ++;
- }
- }
- break;
-
- case BT_VERTICAL:
- {
- if (linelen <= ActualBlock.start_column)
- {
- /* only '\n' */
- if (string)
- *ptr ++ = '\n';
- else
- length ++;
- }
- else if (linelen <= ActualBlock.end_column)
- {
- if (string)
- {
- strcpy (ptr, text + ActualBlock.start_column);
- ptr += strlen (ptr);
-
- *ptr ++ = '\n';
- }
- else
- length += linelen - ActualBlock.start_column + 2;
- }
- else /* line is longer than block wide */
- {
- linelen = ActualBlock.end_column -
- ActualBlock.start_column + 1;
-
- if (string)
- {
- strncpy (ptr, text + ActualBlock.start_column,
- linelen);
- ptr += linelen;
-
- *ptr ++ = '\n';
- }
- else
- length += linelen;
- }
- }
- break;
- } /* switch */
- }
-
- if (string && ptr-string > length)
- {
- D(bug("Aborting ... String exceeds "
- "(%ld:%ld) )buffer in line %ld !\n",
- ptr-string, length, line));
- }
-
- if (string)
- break; /* done ! */
- else
- {
- string = malloc (length+256); /* allocate memory */
- ptr = string; /* points to EOS */
- }
-
- /* after the loop, the string must be non-NULL, else we didn't get the
- memory ! */
- } while (string != NULL);
-
- if (string) /* add '\0' */
- {
- *ptr = 0;
-
- if (length != strlen (string)+1)
- {
- D(bug("Fehler: length: %ld strlen: %ld\n",
- length, strlen(string)+1));
- }
- }
- }
- else
- string = NULL;
-
- return (string);
- } /* block_to_string */
-
-
- /*****************************************************************************
-
- NAME
- do_bdelete
-
- PARAMETER
- void
-
- RETURN
- void
-
- DESCRIPTION
- Deletes the marked block from the text.
-
- ******************************************************************************/
-
- void do_bdelete (void)
- {
- long lines;
- ED * bep = ActualBlock.ep;
- ED * saveed = Ep;
-
- /* is there a valid block ? */
- if (!block_ok ())
- return;
-
- /* TODO */
- if (ActualBlock.type != BT_LINE)
- {
- error ("bdelete:\nCannot use for this\ntype of block.");
- return;
- }
-
- /* don't allow it in VIEWMODE */
-
- if (bep->viewmode)
- {
- error ("%s:\nCannot delete from a\nwrite-protected text", av[0]);
- return;
- } /* if */
-
- /* change editor */
-
- switch_ed (bep);
-
- /* length of block */
-
- lines = ActualBlock.end_line - ActualBlock.start_line + 1;
-
- /* if line is inside the block, move to start of block. If it is
- beyond the end-line, move up */
-
- if (bep->line >= ActualBlock.start_line && bep->line <= ActualBlock.end_line)
- bep->line = ActualBlock.start_line;
- else if (bep->line > ActualBlock.end_line)
- bep->line -= lines;
-
- /* same for the 1st line */
-
- if (bep->topline >= ActualBlock.start_line && bep->topline <= ActualBlock.end_line)
- bep->topline = ActualBlock.start_line;
- else if (bep->topline > ActualBlock.end_line)
- bep->topline -= lines;
-
- /* free memory and copy lines from beyond the block back */
-
- freelist (bep->list + ActualBlock.start_line, lines);
- bmovl (bep->list + ActualBlock.end_line + 1,
- bep->list + ActualBlock.start_line,
- bep->lines - ActualBlock.end_line - 1);
-
- /* adjust number of lines. Text has been modified */
-
- bep->lines -= lines;
- bep->modified = 1;
-
- /* move cursor if it's now outside the text */
-
- if (bep->line >= bep->lines)
- bep->line = bep->lines - 1;
-
- /* move topline if it's now outside the text */
-
- if (bep->topline >= bep->lines)
- bep->topline = bep->lines - 1;
-
- /* no lines in text ? */
-
- if (bep->line < 0)
- bep->topline = bep->line = 0;
-
- /* create at least one line */
-
- if (bep->lines == 0)
- {
- bep->lines ++;
- SETLINE(bep,0,allocline(1));
- }
-
- /* get current line */
- text_load ();
-
- /* no block anymore */
- ActualBlock.type = BT_NONE;
-
- /* always redisplay */
- text_adjust (TRUE);
-
- /* adjust scroller */
- prop_adj ();
-
- /* old editor */
- switch_ed (saveed);
- } /* do_bdelete */
-
-
- /*****************************************************************************
-
- NAME
- do_bcopy
-
- PARAMETER
- void
-
- RETURN
- void
-
- DESCRIPTION
- Copies a block to the line above the cursor. It is possible to
- copy the block into itself thus making it bigger.
-
- ******************************************************************************/
-
- void do_bcopy (void)
- {
- LINE * list;
- long lines,
- i;
- ED * ep = Ep;
- UBYTE * str;
-
- /* update line */
-
- text_sync ();
-
- /* No valid block ? */
- if (!block_ok ())
- return;
-
- /* TODO */
- if (ActualBlock.type != BT_LINE)
- {
- error ("bcopy:\nCannot use for this\ntype of block.");
- return;
- }
-
- /* get length of block */
-
- lines = ActualBlock.end_line - ActualBlock.start_line + 1;
-
- /* make sure we have enough space */
-
- if (extend (ep, lines))
- {
- /* get memory for lines */
-
- if (list = (LINE *)alloclptr(lines))
- {
- /* copy lines to buffer */
-
- bmovl (ActualBlock.ep->list+ActualBlock.start_line, list, lines);
-
- /* make room for the lines */
-
- bmovl (ep->list+ep->line, ep->list+ep->line+lines,
- ep->lines-ep->line);
-
- /* now copy each separate line */
-
- for (i = 0; i < lines; i ++)
- {
- /* get memory for one line */
-
- str = allocline (LENGTH ((char *)list[i]) + 1);
-
- /* no more memory ? */
-
- if (!str)
- {
- /* set error */
-
- nomemory ();
-
- /* free memory */
-
- FreeMem (list, lines * sizeof(LINE));
- freelist (ep->list + ep->line, i);
-
- /* make space for block disappear */
-
- bmovl (ep->list+ep->line+lines, ep->list+ep->line,
- ep->lines-ep->line);
-
- return;
- }
-
- /* copy contents */
-
- strcpy ((char *)str, (char *)list[i]);
-
- /* add line to list */
-
- SETLINE(ep,ep->line+i,str);
- }
-
- /* free buffer */
-
- FreeMem (list, lines * sizeof(LINE));
-
- /* if we inserted the block before the start of the block,
- we must adjust it */
-
- if (ep == ActualBlock.ep)
- {
- if (ep->line <= ActualBlock.start_line)
- {
- ActualBlock.start_line += lines;
- ActualBlock.end_line += lines;
- } else if (ep->line <= ActualBlock.end_line)
- ActualBlock.end_line += lines;
- }
-
- /* Text has been modified. Also the number of lines has changed. */
-
- ep->modified = 1;
- ep->lines += lines;
-
- #ifdef NOTDEF
- /* update display */
- if (!text_adjust (FALSE))
- {
- scroll_display (0, -lines, ep->topcolumn, ep->line,
- ep->topcolumn+Columns, ep->topline+Lines);
- }
- #endif
-
- /* Move cursor to the bottom */
-
- ep->line += lines;
-
- /* get new contents */
-
- text_load ();
-
- if (!text_adjust (FALSE)) /* display is adjusted, if needed */
- {
- scroll_display (0, -lines, ep->topcolumn, ep->line-lines,
- ep->topcolumn+Columns, ep->topline+Lines-1);
- }
-
- /* adjust scroller */
- prop_adj ();
- } else
- nomemory ();
- } else
- nomemory ();
- } /* do_bcopy */
-
-
- /*****************************************************************************
-
- NAME
- do_bmove
-
- PARAMETER
- void
-
- RETURN
- void
-
- DESCRIPTION
- Moves the marked block between the current line and the line
- above it. It's not possible to move the block into itself.
-
- ******************************************************************************/
-
- void do_bmove (void)
- {
- long lines;
- LINE * list;
- ED * ep = Ep;
-
- /* update text */
-
- text_sync ();
-
- /* no block ?? */
- if (!block_ok ())
- return;
-
- /* TODO */
- if (ActualBlock.type != BT_LINE)
- {
- error ("bmove:\nCannot use for this\ntype of block.");
- return;
- }
-
- /* not allowed in viewmode */
-
- if (ActualBlock.ep->viewmode)
- {
- error ("%s:\nCannot move from a\nwrite-protected text", av[0]);
- return;
- } /* if */
-
- /* it is not very usefull to move a block into itself */
-
- if ( ActualBlock.ep == ep &&
- ep->line >= ActualBlock.start_line &&
- ep->line <= ActualBlock.end_line )
- {
- error ("bmove:\nCannot move a\nblock into itself");
- return;
- }
-
- /* length of block */
-
- lines = ActualBlock.end_line - ActualBlock.start_line + 1;
-
- /* get memory for a copy of the block */
-
- if (!(list = (LINE *)alloclptr (lines)))
- {
- nomemory ();
- return;
- }
-
- /* text has been modified */
- ActualBlock.ep->modified = ep->modified = 1;
-
- /* copy block to tmp. memory */
- bmovl (ActualBlock.ep->list + ActualBlock.start_line, list, lines);
-
- /* are we in the editor that has the block or do we have to move the
- block to some other editor ? */
- if (ep == ActualBlock.ep)
- {
- /* behind the block: move the lines behind the block upto the current
- line up to the line where the block started and copy the former
- block into the new space */
-
- if (ep->line > ActualBlock.start_line)
- {
- bmovl ( ep->list + ActualBlock.end_line + 1,
- ep->list + ActualBlock.start_line,
- ep->line - ActualBlock.end_line -1);
- bmovl (list, ep->list + ep->line - lines, lines);
- } else
- { /* before the block: copy all lines from the current upto
- the line where the block began up to the block-end
- and copy the former block into the new space */
-
- bmovl (ep->list + ep->line, ep->list + ep->line + lines,
- ActualBlock.start_line - ep->line);
- bmovl (list, ep->list + ep->line, lines);
-
- /* move down */
- ep->line += lines;
- }
-
- /* load (new) current line */
- text_load ();
- } else
- { /* move block between editors */
-
- /* make room in the editor that gets the block */
- if (extend (ep, lines))
- {
- /* copy the lines after the block the beginning of the block
- thus deleting him */
-
- bmovl ( ActualBlock.ep->list + ActualBlock.end_line + 1,
- ActualBlock.ep->list + ActualBlock.start_line,
- ActualBlock.ep->lines - ActualBlock.end_line - 1);
-
- /* make room in the list of lines for the block */
- bmovl ( ep->list + ep->line,
- ep->list + ep->line + lines,
- ep->lines - ep->line);
-
- /* copy the buffer to its new place */
- bmovl (list, ep->list + ep->line, lines);
-
- /* adjust the number of lines both editors have now */
- ep->lines += lines; /* he gets the block */
- ActualBlock.ep->lines -= lines; /* he lost it */
-
- /* the current line in the editor that had the block was inside
- the block */
- if ( ActualBlock.ep->line >= ActualBlock.start_line &&
- ActualBlock.ep->line <= ActualBlock.end_line )
- {
- /* move cursor to the place where the block started */
- ActualBlock.ep->line = ActualBlock.start_line;
-
- /* if the block was the last thing in this text, move up
- one more line */
- if (ActualBlock.ep->line == ActualBlock.ep->lines)
- ActualBlock.ep->line --;
- }
-
- /* if the line was behind the last line of the block, move up
- the length of the block in lines. */
- if (ActualBlock.ep->line > ActualBlock.end_line)
- ActualBlock.ep->line -= lines;
-
- /* ... but not too far */
- if (ActualBlock.ep->line < 0)
- ActualBlock.ep->line = 0;
-
- /* no block anymore */
- ActualBlock.type = BT_NONE;
-
- /* if we moved the whole text, make sure the old editor
- al least contains one single line */
- if (ActualBlock.ep->lines == 0)
- {
- LINE ptr = allocline (1);
-
- SETLINE(ActualBlock.ep,0,ptr);
- ActualBlock.ep->lines ++;
- }
-
- ep->line += lines; /* Move cursor down */
-
- text_load (); /* text_switch() calls text_sync() ! */
- switch_ed (ActualBlock.ep); /* make source to the active editor */
-
- if (!Ep->iconmode)
- { /* Not iconified */
- text_adjust (TRUE);
-
- /* adjust scroller */
- prop_adj ();
- }
-
- switch_ed (ep); /* old Ed */
- }
- }
-
- ActualBlock.type = BT_NONE; /* We don't have any block anymore */
-
- /* free tmp. buffer */
- FreeMem (list, lines * sizeof(LINE));
-
- /* force redisplay */
- text_adjust (TRUE);
- } /* do_bmove */
-
-
- /*****************************************************************************
-
- NAME
- do_bsource
-
- PARAMETER
- void
-
- RETURN
- void
-
- DESCRIPTION
- Executes all lines inside a block as if they were typed as commands.
- The block is removed before the execution starts. The text
- is updated before every line. Thus self-modifying code is possible.
-
- NOTE
- - since the start and end lines are loaded immediately and the
- block unblock'd before execution starts, you can theoretically have
- another BSOURCE as part of this BSOURCE (but be carefull!).
- - BSOURCE allows self-modifying code
-
- ******************************************************************************/
-
- void do_bsource (void)
- {
- ED * ep;
- char buf[MAXLINELEN];
- int i, start, end;
-
- if (!block_ok ())
- return;
-
- /* TODO */
- if (ActualBlock.type != BT_LINE)
- {
- error ("bsource:\nCannot use for this\ntype of block.");
- return;
- }
-
- /* find start and end */
-
- ep = ActualBlock.ep;
- start = ActualBlock.start_line;
- end = ActualBlock.end_line + 1;
-
- /* unblock */
-
- text_redrawblock (0);
-
- /* execute every line */
-
- for (i = start; i < end; i ++)
- {
- text_sync (); /* make sure we are using the latest text */
-
- if (*(GETTEXT(ep,i)) != '#')
- {
- strcpy (buf, GETTEXT(ep,i));
-
- if (!do_command (buf))
- break;
- }
- }
- } /* do_bsource */
-
-
- /******************************************************************************
- ***** ENDE block.c
- ******************************************************************************/
-