/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 1997 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2016 by Delphix. All rights reserved. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ /* Copyright (c) 1979 Regents of the University of California */ /*LINTLIBRARY*/ #include #include #include "curses_inc.h" /* * Put the character string cp out, with padding. * The number of affected lines is affcnt, and the routine * used to output one character is outc. */ static char *ocp; static char * _tpad(char *, int, int (*)(char)); static char * _tpad(char *cp, int affcnt, int (*outc)(char x)) { int delay = 0; char *icp = cp; int ignorexon = 0, doaffcnt = 0; #ifdef _VR2_COMPAT_CODE /* * Why is this here? * Because mandatory padding must be used for flash_screen * and bell. We cannot force users to code mandatory padding * in their terminfo entries, as that would break compatibility. * We therefore, do it here. * * When compatibility is to be broken, it will go away * and users will be informed that they MUST use mandatory * padding for flash and bell. */ if (ocp == bell || ocp == flash_screen) ignorexon = TRUE; #endif /* _VR2_COMPAT_CODE */ /* Eat initial $< */ cp += 2; /* Convert the number representing the delay. */ if (isdigit(*cp)) { do delay = delay * 10 + *cp++ - '0'; while (isdigit(*cp)); } delay *= 10; if (*cp == '.') { cp++; if (isdigit(*cp)) delay += *cp - '0'; /* Only one digit to the right of the decimal point. */ while (isdigit(*cp)) cp++; } /* * If the delay is followed by a `*', then * multiply by the affected lines count. * If the delay is followed by a '/', then * the delay is done irregardless of xon/xoff. */ /*CONSTCOND*/ while (TRUE) { if (*cp == '/') ignorexon = TRUE; else if (*cp == '*') doaffcnt = TRUE; else break; cp++; } if (doaffcnt) delay *= affcnt; if (*cp == '>') cp++; /* Eat trailing '>' */ else { /* * We got a "$<" with no ">". This is usually caused by * a cursor addressing sequence that happened to generate * $ < . To avoid an infinite loop, we output the $ here * and pass back the rest. */ (*outc)(*icp++); return (icp); } /* * If no delay needed, or output speed is * not comprehensible, then don't try to delay. */ if (delay == 0) return (cp); /* * Let handshaking take care of it - no extra cpu load from pads. * Also, this will be more optimal since the pad info is usually * worst case. We only use padding info for such terminals to * estimate the cost of a capability in choosing the cheapest one. * Some capabilities, such as flash_screen, really want the * padding irregardless. */ if (xon_xoff && !ignorexon) return (cp); (void) _delay(delay, outc); return (cp); } int tputs(char *cp, int affcnt, int (*outc)(char)) { if (cp != 0) { ocp = cp; /* The guts of the string. */ while (*cp) if (*cp == '$' && cp[1] == '<') cp = _tpad(cp, affcnt, outc); else (*outc)(*cp++); } return (OK); }