aboutsummaryrefslogtreecommitdiff
path: root/pkg/tbtables/tbzsft.x
blob: a0b1407d6ab4ed46ff6bbb1563dd1dc26a5ac07f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
include "tbtables.h"
include "tblerr.h"

# tbzsft -- Z shift rows
# Shift one or more rows down (to leave a gap in the table) or up (to
# delete rows).  The range of rows that is shifted is from FIRST to
# the last row in the table.  Shift down if SHIFT > 0, or shift up if
# SHIFT < 0.  SHIFT is the number of rows by which to shift.
#
# If SHIFT > 0 rows that are exposed by the shift are NOT set to indef.
# If SHIFT < 0 rows at the end WILL be set to indef.
# In either case the number of rows TB_NROWS(tp) will be updated.
#
# Phil Hodge, 31-Jan-1992  Subroutine created.

procedure tbzsft (tp, first, shift)

pointer tp			# i: pointer to table descriptor
int	first			# i: first row to be affected by the shift
int	shift			# i: shift by this many rows
#--
pointer cptr			# pointer to a column descriptor
pointer v			# pointer to array of values
int	abs_shift		# absolute value of shift
int	row1, row2		# range of rows to be copied
int	nrows			# number of rows written to table
int	dtype			# data type of a column
int	col			# loop index for column number
int	ip, op			# loop indexes
pointer tbcnum()

begin
	nrows = TB_NROWS(tp)

	# Make sure there are enough rows allocated in the table.
	if (first > nrows) {
	    if (shift > 0) {
		row2 = shift + first - 1
		if (row2 > TB_ALLROWS(tp)) {
		    call tbtchs (tp, -1, -1, -1, row2)
		}
	    }
	    return					# nothing else to do
	} else {
	    row2 = shift + nrows
	    if (row2 > TB_ALLROWS(tp)) {
		call tbtchs (tp, -1, -1, -1, row2)
	    }
	}

	if (shift == 0)
	    return

	# Consider the case of deleting all rows starting with FIRST.
	if (nrows + shift < first) {
	    call tbznll (tp, first, nrows)
	    TB_NROWS(tp) = max (0, first-1)
	    return
	}

	if (shift > 0)
	    TB_NROWS(tp) = TB_NROWS(tp) + shift

	abs_shift = abs (shift)

	# Rows row1:row2 will be copied to row1+shift:row2+shift.
	if (shift < 0)
	    row1 = first + abs_shift
	else
	    row1 = first
	row2 = nrows

	do col = 1, TB_NCOLS(tp) {

	    cptr = tbcnum (tp, col)
	    dtype = COL_DTYPE(cptr)
	    v = COL_OFFSET(cptr)		# pointer to column values

	    if (dtype == TBL_TY_DOUBLE) {

		if (shift < 0) {
		    op = first
		    do ip = row1, row2 {
			Memd[v+op-1] = Memd[v+ip-1]
			op = op + 1
		    }

		} else {			# shift > 0
		    op = nrows + shift
		    do ip = row2, row1, -1 {
			Memd[v+op-1] = Memd[v+ip-1]
			op = op - 1
		    }
		}

	    } else if (dtype == TBL_TY_INT) {

		if (shift < 0) {
		    op = first
		    do ip = row1, row2 {
			Memi[v+op-1] = Memi[v+ip-1]
			op = op + 1
		    }

		} else {			# shift > 0
		    op = nrows + shift
		    do ip = row2, row1, -1 {
			Memi[v+op-1] = Memi[v+ip-1]
			op = op - 1
		    }
		}

	    } else if (dtype < 0 || dtype == TBL_TY_CHAR) {

		call malloc (v, SZ_LINE, TY_CHAR)
		if (shift < 0) {
		    op = first
		    do ip = row1, row2 {
			call tbegtt (tp, cptr, ip, Memc[v], SZ_LINE)
			call tbeptt (tp, cptr, op, Memc[v])
			op = op + 1
		    }

		} else {			# shift > 0
		    op = nrows + shift
		    do ip = row2, row1, -1 {
			call tbegtt (tp, cptr, ip, Memc[v], SZ_LINE)
			call tbeptt (tp, cptr, op, Memc[v])
			op = op - 1
		    }
		}
		call mfree (v, TY_CHAR)

	    } else {
		call error (ER_TBCOLBADTYP,
			"tbzsft:  table or memory corrupted?")
	    }
	}

	# If rows were deleted, set the extra rows at end to indef,
	# and change the value of TB_NROWS(tp).
	if (shift < 0) {
	    call tbznll (tp, nrows-abs_shift+1, nrows)
	    TB_NROWS(tp) = max (0, nrows - abs_shift)
	}
end