/**************************************************** * vt100 emulator - remote character interpretation * * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 * v2.5 870214 DBW - more additions (see readme file) * v2.4 861214 DBW - lots of fixes/additions (see readme file) * v2.3 861101 DBW - minor bug fixes * v2.2 861012 DBW - more of the same * v2.1 860915 DBW - new features (see README) * 860823 DBW - Integrated and rewrote lots of code * v2.0 860803 DRB - Rewrote the control sequence parser * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes * v1.0 860712 DBW - First version released * ****************************************************/ #include "vt100.h" static int p[10]; static int numpar; static char escseq[40]; /************************************************ * function to handle remote characters *************************************************/ void doremote(c) char c; { if (c == 24) { inesc = 0; inctrl = 0; return; } if (c == 27 || (inesc >= 0 && c >= ' ')) { doesc(c); return; } if (inctrl >= 0 && c >= ' ') { doctrl(c); return; } if (c == 10 || c == 11 || c == 12) { if (nlmode) doindex('E'); else doindex('D'); return; } if (c == 13) { if (!nlmode) emit(c); return; } if (c == 15) { alt = 0; return; } if (c == 14) { alt = 1; return; } if (a[alt] && c > 94 && c < 127) { doalt(c); return; } emit(c); } void doesc(c) char c; { if (inesc < 0) { inesc = 0; return; } if (c == 27 || c == 24) { inesc = -1; return; } if (c < ' ' || c == 127) return; /* Ignore control chars */ /* Collect intermediates */ if (c < '0') {escseq[inesc++] = c; return; } /* by process of elimination, we have a final character. Put it in the buffer, and dispatch on the first character in the buffer */ escseq[inesc] = c; inesc = -1; /* No longer collecting a sequence */ switch (escseq[0]) /* Dispatch on the first received */ { case '[': /* Control sequence introducer */ numpar = 0; /* No parameters yet */ private = 0; /* Not a private sequence (yet?) */ badseq = 0; /* Good until proven bad */ p[0] = p[1] = 0; /* But default the first parameter */ inctrl = 0; /* We are in a control sequence */ return; /* All done for now ... */ case 'D': case 'E': case 'M': /* Some kind of index */ doindex (c); /* Do the index */ return; /* Return */ case '7': /* Save cursor position */ savx = x; savy = y; savmode = curmode; savalt = alt; sa[0] = a[0]; sa[1] = a[1]; return; case '8': /* Restore cursor position */ x = savx; y = savy; alt = savalt; curmode = savmode; a[0] = sa[0]; a[1] = sa[1]; return; case 'c': /* Reset */ top = MINY; bot = MAXY; savx = MINX; savy = MINY; curmode = FS_NORMAL; p_keyapp = 0; p_curapp = 0; inesc = -1; a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0; redoutil(); emit(12); return; case '(': /* Change character set */ if (c == '0' || c == '2') a[0] = 1; else a[0] = 0; return; case ')': /* Change the other character set */ if (c == '0' || c == '2') a[1] = 1; else a[1] = 0; return; case '=': /* set keypad application mode */ p_keyapp = 1; redoutil(); return; case '>': /* reset application mode */ p_keyapp = 0; redoutil(); return; case 'Z': sendchar(27); sendstring("[?1;7c"); return; /* If we didn't match anything, we can just return, happy in the knowledge that we've at least eaten the whole sequence */ } /* End of switch */ return; } void doctrl(c) char c; { int i; if (c == 27 || c == 24) { inctrl = -1; return; } if (c < ' ' || c == 127) return; /* Ignore control chars */ /* First, look for some parameter characters. If the very first parameter character isn't a digit, then we have a private sequence */ if (c >= '0' && c < '@') { /* can't have parameters after intermediates */ if (inctrl > 0) {badseq++ ; return; } switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': p[numpar] = p[numpar] * 10 + (c - '0'); return; case ';': p[++numpar] = 0; /* Start a new parameter */ return; case '<': case '=': case '>': case '?': /* Can only mean private */ /* Only allowed BEFORE parameters */ if (inctrl == 0) private = c; return; /* if we come here, it's a bad sequence */ } badseq++; /* Flag the bad sequence */ } if (c < '0') /* Intermediate character */ { escseq[inctrl++] = c; /* Save the intermediate character */ return; } /* if we get here, we have the final character. Put it in the escape sequence buffer, then dispatch the control sequence */ numpar++; /* Reflect the real number of parameters */ escseq[inctrl++] = c; /* Store the final character */ escseq[inctrl] = '\000'; /* Tie off the buffer */ inctrl = -1; /* End of the control sequence scan */ /* Don't know how to do most private sequences right now, so just punt them */ if ((private != 0 && private != '?') || badseq != 0) return; if (private == '?' && escseq[0] != 'h' && escseq[0] != 'l') return; switch (escseq[0]) /* Dispatch on first intermediate or final */ { case 'A': if (p[0]<=0) p[0] = 1; y -= 8*p[0]; if (ybot) y = bot; return; case 'C': if (p[0]<=0) p[0] = 1; x += 8*p[0]; if (x>MAXX) x = MAXX; return; case 'D': if (p[0]<=0) p[0] = 1; x -= 8*p[0]; if (x MAXY) y = MAXY; if (x > MAXX) x = MAXX; if (y < MINY) y = MINY; if (x < MINX) x = MINX; return; case 'L': /* ANSI insert line */ case 'M': /* ANSI delete line */ if (p[0] <= 0) p[0] = 1; ScrollRaster(mywindow->RPort,0L, (long)((escseq[0] == 'M' ? 8L : -8L) * p[0]), (long)MINX,(long)y-6,(long)(MAXX+7),(long)bot+1); return; case 'r': /* Set scroll region */ if (p[0] <= 0) p[0] = 1; if (p[1] <= 0) p[1] = p_lines; top = (--p[0]*8)+MINY; bot = (--p[1]*8)+MINY; if (top < MINY) top = MINY; if (bot > MAXY) bot = MAXY; if (top > bot) { top = MINY; bot = MAXY; } x = MINX; y = MINY; return; case 'm': /* Set graphic rendition */ for (i=0;iRPort,0L); if (p[0] == 0) { if (y < MAXY) RectFill(mywindow->RPort, (long)MINX,(long)(y+2),(long)(MAXX+7),(long)(MAXY+1)); } else if (p[0] == 1) { if (y > MINY) RectFill(mywindow->RPort, (long)MINX,(long)(MINY-6),(long)(MAXX+7),(long)(y-7)); } else RectFill(mywindow->RPort, (long)MINX,(long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1)); SetAPen(mywindow->RPort,1L); doerase(); return; case 'h': /* Set parameter */ if (private == 0 && p[0] == 20) nlmode = 1; else if (private == '?') { if (p[0] == 7) p_wrap = 1; else if (p[0] == 1) p_curapp = 1; redoutil(); } return; case 'l': /* Reset parameter */ if (private == 0 && p[0] == 20) nlmode = 0; else if (private == '?') { if (p[0] == 7) p_wrap = 0; else if (p[0] == 1) p_curapp = 0; redoutil(); } return; case 'x': sendchar(27); sendstring("[3;1;8;64;64;1;0x"); return; case 'n': if (p[0] == 6) { sendchar(27); sprintf(escseq,"[%d;%dR",((y-MINY)/8)+1,((x-MINX)/8)+1); sendstring(escseq); return; } sendchar(27); sendstring("[0n"); return; case 'c': sendchar(27); sendstring("[?1;7c"); return; } /* Don't know how to do this one, so punt it */ } void doindex(c) char c; { if (c != 'M') { if (c == 'E') x = MINX; if (y > bot) if (y < MAXY) y += 8; if (y == bot) ScrollRaster(mywindow->RPort,0L,8L,(long)MINX,(long)(top-6), (long)(MAXX+7),(long)(bot+1)); if (y < bot) y += 8; } else { if (y < top) if (y > MINY) y -= 8; if (y == top) ScrollRaster(mywindow->RPort,0L,-8L,(long)MINX,(long)(top-6), (long)(MAXX+7),(long)(bot+1)); if (y > top) y -= 8; } return; } doalt(c) char c; { int oldx,newx; inesc = -1; oldx = x; emit(' '); newx = x; x = oldx; SetAPen(mywindow->RPort,1L); switch (c) { case 'a': doline(0,-6,8,1); break; case 'j': case 'm': case 'v': doline(4,-6,4,-2); if (c=='j') doline(0,-2,4,-2); else if (c=='m') doline(4,-2,8,-2); else doline(0,-2,8,-2); break; case 'k': case 'l': case 'w': doline(4,-2,4,1); if (c=='k') doline(0,-2,4,-2); else if (c=='l') doline(4,-2,8,-2); else doline(0,-2,8,-2); break; case 'n': case 'q': doline(0,-2,8,-2); if (c=='n') doline(4,-6,4,2); break; case 't': case 'u': case 'x': doline(4,-6,4,1); if (c=='t') doline(4,-2,8,-2); else if (c=='u') doline(0,-2,4,-2); break; } x = newx; } doline(x1,y1,x2,y2) { RectFill(mywindow->RPort,(long)(x+x1),(long)(y+y1), (long)(x+x2),(long)(y+y2)); } void doerase() { if (p[0] < 0) p[0] = 0; SetAPen(mywindow->RPort,0L); if (p[0] == 0) RectFill(mywindow->RPort,(long)x,(long)(y-6), (long)(MAXX+7),(long)(y+1)); else if (p[0] == 1) RectFill(mywindow->RPort, (long)MINX,(long)(y-6),(long)(x+7),(long)(y+1)); else RectFill(mywindow->RPort, (long)MINX,(long)(y-6),(long)(MAXX+7),(long)(y+1)); SetAPen(mywindow->RPort,1L); return; }