static char sccsid
[] = "@(#)subr.c 4.2 (Berkeley) %G%";
* subr.c: general subroutines for fed.
* initialize: various one time initializations.
/* Initialize random variables */
* Initialize value of sqrtmat. This is a constant table
* so we don't have to redo all these square roots when the pen
sqrtmat
[i
][j
] = sqrt((float) i
*i
+ j
*j
);
/* Initialize base locations on screen. These remain fixed. */
base
[NCOL
*i
+j
].c
= (GLCOL
+GLPAD
) * j
+ 1;
base
[NCOL
*i
+j
].r
= SCRHI
- (GLROW
+GLPAD
+10) * i
- GLROW
- 3;
setbuf(stdout
, stoutbuf
);
curzoom
= 1; /* default is zoomed completely out */
* showfont: Wipe clean the screen, display the font
* in a properly spaced fashion, wait for a char to be typed, if it's
* p print the font, then clear the screen and ungetc the char.
register int i
, cr
, cc
, nc
;
message("Show font from <char>");
sprintf(msgbuf
, "Show font from %s to <char>", rdchar(minc
));
zermat(tmpbuf
, GLROW
, GLCOL
);
cr
= SCRHI
-GLROW
; cc
= 3;
for (i
=minc
; i
<=maxc
; i
++) {
if (disptable
[i
].nbytes
) {
* We really should try to find out how far to the
* left the glyph goes so we don't run off the left
* end of the screen, but this is hard, so we fake it.
* Usually glyphs don't run past the left so it's OK.
if (cc
- disptable
[i
].left
< 0)
nc
= cc
+ disptable
[i
].width
;
cr
-= 85; /* Should be GLROW but 4*100>360 */
break; /* Screen full. Just stop. */
dispmsg(rdchar(i
), cc
, cr
, 2);
placechar(i
, cr
+BASELINE
, cc
, tmpbuf
);
if (nextcmd
!= 'Q' && nextcmd
!= 'E' && nextcmd
!= 'N')
* typein: Like showfont but takes a line of text from the user
* and "typesets" it on the screen.
register int i
, cr
, cc
, nc
;
readline("Input line to be typeset: ", msgtype
, sizeof msgtype
);
zermat(tmpbuf
, GLROW
, GLCOL
);
cr
= SCRHI
-GLROW
; cc
= 3;
for (p
=msgtype
; *p
; p
++) {
if (disptable
[i
].nbytes
) {
if (cc
- disptable
[i
].left
< 0)
nc
= cc
+ disptable
[i
].width
;
cr
-= 85; /* Should be GLROW but 4*100>360 */
break; /* Screen full. Just stop. */
dispmsg(rdchar(i
), cc
, cr
, 2);
placechar(i
, cr
+BASELINE
, cc
, tmpbuf
);
if (nextcmd
!= 'Q' && nextcmd
!= 'E' && nextcmd
!= 'N')
* placechar: draw the character ch at position (llr, llc) on the screen.
* Position means the logical center of the character. zero is a GLROW x GLCOL
* matrix of zeros which is needed for comparison, that is, we assume that
* the spot on the screen where this is going is blank, so the chars better
placechar(ch
, llr
, llc
, zero
)
glbuf
= findbits(ch
, GLROW
, GLCOL
, 0, 0, &roff
, &coff
);
fprintf(trace
, "placechar('%s'), roff=%d, coff=%d, llr=%d, llc=%d, down=%d, left=%d, r=%d, c=%d\n", rdchar(ch
), roff
, coff
, llr
, llc
, disptable
[ch
].down
, disptable
[ch
].left
, llr
-disptable
[ch
].down
, llc
-disptable
[ch
].left
);
update(zero
, glbuf
, GLROW
, GLCOL
, llr
-GLROW
+roff
, llc
-coff
);
fprintf(trace
, "placechar, free %x\n", glbuf
);
* redraw: The screen has gotten screwed up somehow.
* Assume nothing but make it look right.
if (wind
[i
].onscreen
!= NULL
) {
zermat(wind
[i
].onscreen
, GLROW
, GLCOL
);
/* Print the char at the lower left of the window */
sprintf(msgbuf
, "%s", rdchar(wind
[i
].used
));
dispmsg(msgbuf
, base
[i
].c
, base
[i
].r
-11, 2);
drawbox(base
[curwind
].r
-1, base
[curwind
].c
-1, 1, GLROW
+2, GLCOL
+2);
* findbits: find the data bits of glyph c, wherever they are, and make
* nr x nc bitmat and put them in it, shifted by horoff and vertoff.
findbits(c
, nr
, nc
, horoff
, vertoff
, rcenter
, ccenter
)
int nr
, nc
; /* the size of the dest */
register int r1
, r2
, c1
, c2
;
int tr
, tc
; /* the size of source */
fprintf(trace
, "findbits(c=%s, nr=%d, nc=%d, horoff=%d, vertoff=%d\n", rdchar(c
), nr
, nc
, horoff
, vertoff
);
if (disptable
[c
].nbytes
== 0)
switch (cht
[c
].wherewind
) {
fprintf(trace
, "case -2, saved from prev place\n");
/* Saved from previous place */
/* Ignore horoff/vertoff assuming they are already right */
* Small but important optimization: if the desired result is
* a whole window and the source happens to be in a whole
* window, just return the source pointer. This saves
* lots of memory copies and happens quite often.
if (nr
== GLROW
&& nc
== GLCOL
)
fprintf(trace
, "case -1: first time\n");
/* First time for this glyph: get it from font file */
fseek(fontdes
, (long) fbase
+disptable
[c
].addr
, 0);
tr
= cht
[c
].nrow
; tc
= cht
[c
].ncol
;
if (tr
> GLROW
|| tc
> GLCOL
|| disptable
[c
].nbytes
> WINDSIZE
)
error("glyph too large for window");
*rcenter
= vertoff
+ disptable
[c
].up
;
*ccenter
= horoff
+ disptable
[c
].left
;
fread(source
, disptable
[c
].nbytes
, 1, fontdes
);
fprintf(trace
, "case default, in window %d", cht
[c
].wherewind
);
source
= wind
[cht
[c
].wherewind
].val
;
*rcenter
= vertoff
+ cht
[c
].rcent
;
*ccenter
= horoff
+ cht
[c
].ccent
;
fprintf(trace
, "curchar=%c=%d, tr=%d, tc=%d\n", curchar
, curchar
, tr
, tc
);
dumpmat("before copy, source", source
, tr
, tc
);
/* Copy in the bits into a bitmat of the right size */
r2
= min(GLROW
-vertoff
-1, GLROW
-1);
c2
= min(GLCOL
-horoff
-1, GLCOL
-1);
fprintf(trace
, "findbits copy: r1=%d, r2=%d, c1=%d, c2=%d, horoff=%d, vertoff=%d\n", r1
, r2
, c1
, c2
, horoff
, vertoff
);
setmat(retval
, nr
, nc
, i
+vertoff
, j
+horoff
, mat(source
, tr
, tc
, i
, j
, 6));
dumpmat("result of copy", retval
, nr
, nc
);
* bufmod: called just before a buffer modifying command.
* Makes a backup copy of the glyph so we can undo later.
if (wind
[curwind
].undval
== NULL
)
wind
[curwind
].undval
= newmat(GLROW
, GLCOL
);
bitcopy(wind
[curwind
].undval
, wind
[curwind
].val
, GLROW
, GLCOL
);
und_p_r
= pen_r
; und_p_c
= pen_c
;
und_c_r
= curs_r
; und_c_c
= curs_c
;
* undo: restore the backup copy. We just swap pointers, which is
* the same as interchanging the two matrices. This way, undo is
if (wind
[curwind
].undval
== NULL
) {
error("Nothing to undo");
wind
[curwind
].val
= wind
[curwind
].undval
;
wind
[curwind
].undval
= tmp
;
pen_r
= und_p_r
; pen_c
= und_p_c
;
move(base
[curwind
].c
+pen_c
, base
[curwind
].r
+GLROW
-pen_r
);
curs_r
= und_c_r
; curs_c
= und_c_c
;
* drawline: draw a line of current flavor between the named two points.
* All points are relative to current window.
* The algorithm is that of a simple DDA. This is similar to what the
* hardware of the HP 2648 does but the placing of the points will be
* different (because of thick pens and erasers).
drawline(from_r
, from_c
, to_r
, to_c
)
fprintf(trace
, "drawline from (%d, %d) to (%d, %d)\n", from_r
, from_c
, to_r
, to_c
);
length
= max(abs(to_r
-from_r
), abs(to_c
-from_c
));
* The actual value doesn't matter, we're just avoiding
xinc
= ((float) (to_r
-from_r
))/length
;
yinc
= ((float) (to_c
-from_c
))/length
;
drawpoint(from_r
, from_c
);
x
= from_r
+ 0.5; y
= from_c
+ 0.5;
for (i
=0; i
<length
; i
++) {
drawpoint((int) x
, (int) y
);
* drawpoint: make a point of the current flavor at (r, c).
setmat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
, pencolor
);
setmat(wind
[curwind
].val
, GLROW
, GLCOL
, r
+i
-4, c
+j
-4, pencolor
);
* setcmd: handle the s command. Format: s <what> <where>.
message("set pen <weight>");
case 'f': /* set pen fine */
case 'l': /* set pen light */
case 'h': /* set pen heavy */
case 'b': /* set pen bold */
message("set pen heavy");
error("Illegal kind of pen weight");
case 's': /* set size of heavy pen */
message("set pen size to <size>");
sprintf(msgbuf
, "set pen size to %d", where
);
if (where
> 0 && where
< 10) {
* setpen: set the heavy pen size to s.
* Main work here is defining template of pen.
penmat
[i
][j
] = (radius
>= sqrtmat
[abs(i
-4)][abs(j
-4)]);
* Kludge to make a 2-wide pen possible by specifying 1.
fprintf(trace
, "%c", penmat
[i
][j
] ? 'P' : '.');
* error: print the given error message and return for another command.
* copymove: do a move or copy command.
* cmd is C or M, the command.
sprintf(msgbuf
, "%s <from>", action
);
sprintf(msgbuf
, "%s %s to <to>", action
, rdchar(src
));
strcpy(lochr
, rdchar(src
));
sprintf(msgbuf
, "%s %s to %s", action
, lochr
, rdchar(dest
));
disptable
[dest
] = disptable
[src
];
if (cht
[dest
].wherewind
>= 0)
wind
[cht
[dest
].wherewind
].used
= dest
;
if (cht
[dest
].wherewind
!= -1) {
* Make copies of the window so changing
* one won't change the other.
* The old copy gets the window on the screen, if any,
* relegating the new copy to the background.
cpy
= newmat(GLROW
, GLCOL
);
if (cht
[dest
].wherewind
>= 0)
bitcopy(cpy
, wind
[cht
[src
].wherewind
].val
, GLROW
, GLCOL
);
bitcopy(cpy
, cht
[src
].whereat
, GLROW
, GLCOL
);
if (cht
[dest
].wherewind
== curwind
)
cht
[dest
].wherewind
= -2;
* Move. Delete the old entries.
disptable
[src
].addr
= disptable
[src
].nbytes
= 0;
* cch: make sure there is a current character.
error("No current glyph");
* confirm: if there have been changes, ask user if he is sure.
message("Changes since last write -- Are you sure?");
error("Not sure - aborted");
* delchar: the D command. Delete a character from the buffer.
message("delete <char>");
sprintf(msgbuf
, "delete %s through <char>", rdchar(c1
));
sprintf(msgbuf
, "delete %s through %s", buf
, rdchar(c2
));
if ((w
= cht
[c
].wherewind
) >= 0) {
zermat(wind
[w
].val
, GLROW
, GLCOL
);
* zoom out to full screen so the screen doean't go nuts when we
* print off the current zoom window. Save old value of zoom in
* oldzoom so space can put us back.
* newglyph: the n command.
message("new glyph <char>");
sprintf(msgbuf
, "new glyph %s", rdchar(curchar
));
fprintf(trace
, "\n\nnewglyph(%s)\n", rdchar(curchar
));
if (disptable
[curchar
].nbytes
!= 0) {
fprintf(trace
, "char exists: %s\n", rdchar(curchar
));
sprintf(msgbuf
, "char exists: %s", rdchar(curchar
));
* Not on screen. First find a suitable window,
fprintf(trace
, "chose window %d\n", windno
);
wind
[windno
].used
= curchar
;
/* Put a box around the current window */
drawbox(base
[curwind
].r
-1, base
[curwind
].c
-1, 0, GLROW
+2, GLCOL
+2);
drawbox(base
[windno
].r
-1, base
[windno
].c
-1, 1, GLROW
+2, GLCOL
+2);
/* Print the char at the lower left of the window */
sprintf(msgbuf
, "%s", rdchar(curchar
));
dispmsg(msgbuf
, base
[windno
].c
, base
[windno
].r
-11, 2);
/* Now make room in the window */
if (wind
[windno
].onscreen
== NULL
) {
/* Brand new window, have to allocate space */
wind
[windno
].onscreen
= newmat(GLROW
, GLCOL
);
/* Save prev glyph for later */
cht
[wind
[curchar
].used
].whereat
= wind
[windno
].val
;
cht
[wind
[curchar
].used
].wherewind
= -2;
if (wind
[windno
].undval
!= NULL
) {
fprintf(trace
, "newglyph frees undo: %x\n", wind
[windno
].undval
);
free(wind
[windno
].undval
);
wind
[windno
].undval
= NULL
;
* Vertical & horizontal offsets. Line up the baseline
* of the char at BASELINE from bottom, but center
wind
[windno
].val
= newmat(GLROW
, GLCOL
);
cht
[curchar
].wherewind
= windno
;
cht
[curchar
].rcent
= curs_r
= GLROW
- BASELINE
;
cht
[curchar
].ccent
= curs_c
= GLCOL
/ 2;
dumpmat("wind[windno].onscreen", wind
[windno
].onscreen
, GLROW
, GLCOL
);
* Mung the zoom out to 1 and back. This is needed to
* re-center the glyph on the screen if zoomed in, otherwise
* if you move by one window it puts the cursor way over at
* the right with only half the window visible.
* numedit: change one of the numerical parameters.
message("number of <char>");
sprintf(msgbuf
, "number of %s <field>", rdchar(c
));
&disptable
[c
].addr
; fld
= "addr"; break;
case 'n': sp
= &disptable
[c
].nbytes
; fld
= "nbytes"; break;
case 'u': cp
= &disptable
[c
].up
; fld
= "up"; break;
case 'd': cp
= &disptable
[c
].down
; fld
= "down"; break;
case 'l': cp
= &disptable
[c
].left
; fld
= "left"; break;
case 'r': cp
= &disptable
[c
].right
; fld
= "right"; break;
case 'w': sp
= &disptable
[c
].width
; fld
= "width"; break;
case 's': sp
= (short *) &disptable
[c
].nbytes
;
default: error("No such field");
sprintf(msgbuf
, "number of %s %s (old value %d) is ", rdchar(c
), fld
, ovalue
);
readline(msgbuf
, numb
, sizeof numb
);
* These routines turn the cursor and rubber band line on and off,
* remembering its state for the o and r commands.
x
= base
[curwind
].c
+ curs_c
;
y
= base
[curwind
].r
+ GLROW
- curs_r
- 1;
* fillin - fill in with 1's all the spots that are in the enclosed
* area that (x, y) is in.
if (x
<0 || x
>=GLROW
|| y
<0 || y
>=GLCOL
||
mat(wind
[curwind
].val
, GLROW
, GLCOL
, x
, y
))
setmat(wind
[curwind
].val
, GLROW
, GLCOL
, x
, y
, 1);
* syncwind: make sure that window #n shows on the screen what it's
* supposed to after an arbitrary change.
fprintf(trace
, "syncwind(%d)\n", n
);
update(wind
[n
].onscreen
, wind
[n
].val
, GLROW
, GLCOL
, base
[n
].r
, base
[n
].c
);
bitcopy(wind
[n
].onscreen
, wind
[n
].val
, GLROW
, GLCOL
);
* Embolden artificially emboldens the glyphs in the font by smearing
* them to the right by the current heavy pen size. Or else italicize it.
sprintf(msgbuf
, "Artificially <embolden/italicize/resize/smooth>");
case 'i': case 'I': kind
= ITAL
; strbold
= "italicize"; break;
case 'e': case 'E': kind
= BOLD
; strbold
= "embolden"; break;
case 'r': case 'R': kind
= RESIZE
; strbold
= "resize"; break;
case 's': case 'S': kind
= SMOOTH
; strbold
= "smooth"; break;
default: error("No such artificial operation");
sprintf(msgbuf
, "Artificially %s glyphs from <char>", strbold
);
strcpy(lowch
, rdchar(low
));
sprintf(msgbuf
, "Artificially %s glyphs from %s to <char>", strbold
, lowch
);
sprintf(msgbuf
, "Artificially %s glyphs from %s to %s from <point size>", strbold
, lowch
, rdchar(high
));
sprintf(msgbuf
, "Artificially %s glyphs from %s to %s from %dP to <point size>P", strbold
, lowch
, rdchar(high
), oldps
);
sprintf(msgbuf
, "Artificially %s glyphs from %s to %s from %dP to %dP", strbold
, lowch
, rdchar(high
), oldps
, newps
);
if (oldps
<= 0 || oldps
> 36 || newps
<= 0 || newps
> 36 || oldps
== newps
)
error("Bad point sizes");
sprintf(msgbuf
, "Artificially %s glyphs from %s to %s", strbold
, lowch
, rdchar(high
));
for (cur
=low
; cur
<=high
; cur
++) {
if (curchar
== cur
) { /* e.g. if the getglyph succeeded */
shrinkglyph(oldps
, newps
);
blowupglyph(oldps
, newps
);
* Artificially embolden the current glyph.
int smear
= hpensize
< 2 ? 2 : hpensize
;
for (c
=GLCOL
-1; c
>=smear
; c
--)
if (mat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
-i
))
setmat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
, 1);
* Artificially italicize the current glyph.
register int r
, c
, i
, off
;
int baser
= cht
[curchar
].rcent
; /* GLROW - BASELINE; */
for (r
=0; r
<baser
; r
++) {
off
= (baser
-r
) / SLOPE
+ 0.5;
for (c
=GLCOL
-1; c
>=off
; c
--) {
setmat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
,
mat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
-off
));
setmat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
, 0);
for (r
=baser
; r
<GLROW
; r
++) {
off
= (r
-baser
) * (2.0/7.0) + 0.5;
for (c
=off
; c
<GLCOL
; c
++)
setmat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
-off
,
mat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
));
setmat(wind
[curwind
].val
, GLROW
, GLCOL
, r
, c
, 0);
* Blow up or shrink a glyph from oldps points to newps points.
* The basic idea is that for each on point in the old glyph we
* find the corresponding point in the new glyph and copy the value.
shrinkglyph(oldps
, newps
)
register int or, oc
, nr
, nc
;
int baser
= cht
[curchar
].rcent
;
int basec
= cht
[curchar
].ccent
;
ratio
= (float) newps
/ (float) oldps
;
tmp
= newmat(GLROW
, GLCOL
);
curw
= wind
[curwind
].val
;
bitcopy(tmp
, curw
, GLROW
, GLCOL
);
zermat(curw
, GLROW
, GLCOL
);
for (or=0; or<GLROW
; or++) {
nr
= baser
+ (or-baser
)*ratio
+ 0.5;
for (oc
=0; oc
<GLCOL
; oc
++) {
nc
= basec
+ (oc
-basec
)*ratio
+ 0.5;
if (nr
< 0 || nr
>= GLROW
|| nc
< 0 || nc
>= GLCOL
)
n
= mat(tmp
, GLROW
, GLCOL
, or, oc
);
setmat(curw
, GLROW
, GLCOL
, nr
, nc
, n
);
disptable
[curchar
].width
= disptable
[curchar
].width
* ratio
+ 0.5;
* blow up a glyph. Otherwise like shrinkglyph.
blowupglyph(oldps
, newps
)
register int or, oc
, nr
, nc
;
int baser
= cht
[curchar
].rcent
;
int basec
= cht
[curchar
].ccent
;
ratio
= (float) oldps
/ (float) newps
;
tmp
= newmat(GLROW
, GLCOL
);
curw
= wind
[curwind
].val
;
bitcopy(tmp
, curw
, GLROW
, GLCOL
);
zermat(curw
, GLROW
, GLCOL
);
for (nr
=0; nr
<GLROW
; nr
++) {
or = baser
+ (nr
-baser
)*ratio
+ 0.5;
for (nc
=0; nc
<GLCOL
; nc
++) {
oc
= basec
+ (nc
-basec
)*ratio
+ 0.5;
if (or < 0 || or >= GLROW
|| oc
< 0 || oc
>= GLCOL
)
n
= mat(tmp
, GLROW
, GLCOL
, or, oc
);
setmat(curw
, GLROW
, GLCOL
, nr
, nc
, n
);
disptable
[curchar
].width
= disptable
[curchar
].width
/ ratio
+ 0.5;
* Smooth a glyph. We look for corners and trim the point. Corners of
* both blanks and dots in all 4 orientations are looked for.
int a3
, b2
, b3
, b4
, c1
, c2
, c4
, c5
, d2
, d3
, d4
, e3
;
tmp
= newmat(GLROW
, GLCOL
);
curw
= wind
[curwind
].val
;
bitcopy(tmp
, curw
, GLROW
, GLCOL
);
for (r
=2; r
<GLROW
-2; r
++)
for (c
=2; c
<GLCOL
-2; c
++) {
* where c3 is the square we are interested in
b3
= mat(tmp
, GLROW
, GLCOL
, r
-1, c
);
c2
= mat(tmp
, GLROW
, GLCOL
, r
, c
-1);
c4
= mat(tmp
, GLROW
, GLCOL
, r
, c
+1);
d3
= mat(tmp
, GLROW
, GLCOL
, r
+1, c
);
/* exactly 2 of the 4 neighbors must be dots */
if (b3
+c2
+c4
+d3
!= 2) continue;
c3
= mat(tmp
, GLROW
, GLCOL
, r
, c
);
b2
= mat(tmp
, GLROW
, GLCOL
, r
-1, c
-1);
b4
= mat(tmp
, GLROW
, GLCOL
, r
-1, c
+1);
d2
= mat(tmp
, GLROW
, GLCOL
, r
+1, c
-1);
d4
= mat(tmp
, GLROW
, GLCOL
, r
+1, c
+1);
/* exactly one of the 4 diags must match the center */
if (b2
+b4
+d2
+d4
!= 3 - 2*c3
) continue;
a3
= mat(tmp
, GLROW
, GLCOL
, r
-2, c
);
c1
= mat(tmp
, GLROW
, GLCOL
, r
, c
-2);
c5
= mat(tmp
, GLROW
, GLCOL
, r
, c
+2);
e3
= mat(tmp
, GLROW
, GLCOL
, r
+2, c
);
/* Figure out which of the 4 directions */
if (b3
+c2
+c1
+a3
!= 4*c3
) continue;
if (b3
+c4
+c5
+a3
!= 4*c3
) continue;
if (d3
+c2
+c1
+e3
!= 4*c3
) continue;
if (d3
+c4
+c5
+e3
!= 4*c3
) continue;
/* It must be a corner. Toggle it. */
setmat(curw
, GLROW
, GLCOL
, r
, c
, !c3
);
* Read a number from bottom line ala readline.
* This should probably go in lib2648.
readline(prompt
, buf
, sizeof buf
);
fprintf(trace
, "readline returns '%s', retval=%d\n", buf
, retval
);
bitmat curw
= wind
[curwind
].val
;
message("Invert <horizontally/vertically>");
message("Invert horizontally");
for (r
=0; r
<GLROW
; r
++) {
fprintf(trace
, "row %d\n", r
);
for (c
=0; c
<=(GLCOL
-1)/2; c
++) {
tmp1
= mat(curw
, GLROW
, GLCOL
, r
, c
);
tmp2
= mat(curw
, GLROW
, GLCOL
, r
, GLCOL
-1-c
);
fprintf(trace
, "cols %d (%d) <=> %d (%d)\n", c
, tmp1
, GLCOL
-1-c
, tmp2
);
setmat(curw
, GLROW
, GLCOL
, r
, c
, tmp2
);
setmat(curw
, GLROW
, GLCOL
, r
, GLCOL
-1-c
, tmp1
);
message("Invert vertically");
for (c
=0; c
<GLCOL
; c
++) {
for (r
=0; r
<=(GLROW
-1)/2; r
++) {
tmp1
= mat(curw
, GLROW
, GLCOL
, r
, c
);
tmp2
= mat(curw
, GLROW
, GLCOL
, GLROW
-1-r
, c
);
setmat(curw
, GLROW
, GLCOL
, r
, c
, tmp2
);
setmat(curw
, GLROW
, GLCOL
, GLROW
-1-r
, c
, tmp1
);