Get curses data to display for a process.

        - p is the process to display
        - first is a tag=True if the process is the first on the list

def get_process_curses_data(self, p, first, args):
        """Get curses data to display for a process.

        - p is the process to display
        - first is a tag=True if the process is the first on the list
        """
        ret = [self.curse_new_line()]
        # CPU
        if 'cpu_percent' in p and p['cpu_percent'] is not None and p['cpu_percent'] != '':
            if args.disable_irix and self.nb_log_core != 0:
                msg = self.layout_stat['cpu'].format(p['cpu_percent'] / float(self.nb_log_core))
            else:
                msg = self.layout_stat['cpu'].format(p['cpu_percent'])
            alert = self.get_alert(p['cpu_percent'],
                                   highlight_zero=False,
                                   is_max=(p['cpu_percent'] == self.max_values['cpu_percent']),
                                   header="cpu")
            ret.append(self.curse_add_line(msg, alert))
        else:
            msg = self.layout_header['cpu'].format('?')
            ret.append(self.curse_add_line(msg))
        # MEM
        if 'memory_percent' in p and p['memory_percent'] is not None and p['memory_percent'] != '':
            msg = self.layout_stat['mem'].format(p['memory_percent'])
            alert = self.get_alert(p['memory_percent'],
                                   highlight_zero=False,
                                   is_max=(p['memory_percent'] == self.max_values['memory_percent']),
                                   header="mem")
            ret.append(self.curse_add_line(msg, alert))
        else:
            msg = self.layout_header['mem'].format('?')
            ret.append(self.curse_add_line(msg))
        # VMS/RSS
        if 'memory_info' in p and p['memory_info'] is not None and p['memory_info'] != '':
            # VMS
            msg = self.layout_stat['virt'].format(self.auto_unit(p['memory_info'][1], low_precision=False))
            ret.append(self.curse_add_line(msg, optional=True))
            # RSS
            msg = self.layout_stat['res'].format(self.auto_unit(p['memory_info'][0], low_precision=False))
            ret.append(self.curse_add_line(msg, optional=True))
        else:
            msg = self.layout_header['virt'].format('?')
            ret.append(self.curse_add_line(msg))
            msg = self.layout_header['res'].format('?')
            ret.append(self.curse_add_line(msg))
        # PID
        msg = self.layout_stat['pid'].format(p['pid'], width=self.__max_pid_size())
        ret.append(self.curse_add_line(msg))
        # USER
        if 'username' in p:
            # docker internal users are displayed as ints only, therefore str()
            # Correct issue #886 on Windows OS
            msg = self.layout_stat['user'].format(str(p['username'])[:9])
            ret.append(self.curse_add_line(msg))
        else:
            msg = self.layout_header['user'].format('?')
            ret.append(self.curse_add_line(msg))
        # TIME+
        try:
            # Sum user and system time
            user_system_time = p['cpu_times'][0] + p['cpu_times'][1]
        except (OverflowError, TypeError) as e:
            # Catch OverflowError on some Amazon EC2 server
            # See https://github.com/nicolargo/glances/issues/87
            # Also catch TypeError on macOS
            # See: https://github.com/nicolargo/glances/issues/622
            # logger.debug("Cannot get TIME+ ({})".format(e))
            msg = self.layout_header['time'].format('?')
            ret.append(self.curse_add_line(msg, optional=True))
        else:
            hours, minutes, seconds = seconds_to_hms(user_system_time)
            if hours > 99:
                msg = '{:<7}h'.format(hours)
            elif 0 < hours < 100:
                msg = '{}h{}:{}'.format(hours, minutes, seconds)
            else:
                msg = '{}:{}'.format(minutes, seconds)
            msg = self.layout_stat['time'].format(msg)
            if hours > 0:
                ret.append(self.curse_add_line(msg,
                                               decoration='CPU_TIME',
                                               optional=True))
            else:
                ret.append(self.curse_add_line(msg, optional=True))
        # THREAD
        if 'num_threads' in p:
            num_threads = p['num_threads']
            if num_threads is None:
                num_threads = '?'
            msg = self.layout_stat['thread'].format(num_threads)
            ret.append(self.curse_add_line(msg))
        else:
            msg = self.layout_header['thread'].format('?')
            ret.append(self.curse_add_line(msg))
        # NICE
        if 'nice' in p:
            nice = p['nice']
            if nice is None:
                nice = '?'
            msg = self.layout_stat['nice'].format(nice)
            ret.append(self.curse_add_line(msg,
                                           decoration=self.get_nice_alert(nice)))
        else:
            msg = self.layout_header['nice'].format('?')
            ret.append(self.curse_add_line(msg))
        # STATUS
        if 'status' in p:
            status = p['status']
            msg = self.layout_stat['status'].format(status)
            if status == 'R':
                ret.append(self.curse_add_line(msg, decoration='STATUS'))
            else:
                ret.append(self.curse_add_line(msg))
        else:
            msg = self.layout_header['status'].format('?')
            ret.append(self.curse_add_line(msg))
        # IO read/write
        if 'io_counters' in p and p['io_counters'][4] == 1 and p['time_since_update'] != 0:
            # Display rate if stats is available and io_tag ([4]) == 1
            # IO read
            io_rs = int((p['io_counters'][0] - p['io_counters'][2]) / p['time_since_update'])
            if io_rs == 0:
                msg = self.layout_stat['ior'].format("0")
            else:
                msg = self.layout_stat['ior'].format(self.auto_unit(io_rs,
                                                                    low_precision=True))
            ret.append(self.curse_add_line(msg, optional=True, additional=True))
            # IO write
            io_ws = int((p['io_counters'][1] - p['io_counters'][3]) / p['time_since_update'])
            if io_ws == 0:
                msg = self.layout_stat['iow'].format("0")
            else:
                msg = self.layout_stat['iow'].format(self.auto_unit(io_ws,
                                                                    low_precision=True))
            ret.append(self.curse_add_line(msg, optional=True, additional=True))
        else:
            msg = self.layout_header['ior'].format("?")
            ret.append(self.curse_add_line(msg, optional=True, additional=True))
            msg = self.layout_header['iow'].format("?")
            ret.append(self.curse_add_line(msg, optional=True, additional=True))

        # Command line
        # If no command line for the process is available, fallback to
        # the bare process name instead
        if 'cmdline' in p:
            cmdline = p['cmdline']
        else:
            cmdline = '?'
        try:
            if cmdline:
                path, cmd, arguments = split_cmdline(cmdline)
                if os.path.isdir(path) and not args.process_short_name:
                    msg = self.layout_stat['command'].format(path) + os.sep
                    ret.append(self.curse_add_line(msg, splittable=True))
                    ret.append(self.curse_add_line(cmd, decoration='PROCESS', splittable=True))
                else:
                    msg = self.layout_stat['command'].format(cmd)
                    ret.append(self.curse_add_line(msg, decoration='PROCESS', splittable=True))
                if arguments:
                    msg = ' ' + self.layout_stat['command'].format(arguments)
                    ret.append(self.curse_add_line(msg, splittable=True))
            else:
                msg = self.layout_stat['name'].format(p['name'])
                ret.append(self.curse_add_line(msg, splittable=True))
        except (TypeError, UnicodeEncodeError) as e:
            # Avoid crach after running fine for several hours #1335
            logger.debug("Can not decode command line '{}' ({})".format(cmdline, e))
            ret.append(self.curse_add_line('', splittable=True))

        # Add extended stats but only for the top processes
        if first and 'extended_stats' in p and args.enable_process_extended:
            # Left padding
            xpad = ' ' * 13
            # First line is CPU affinity
            if 'cpu_affinity' in p and p['cpu_affinity'] is not None:
                ret.append(self.curse_new_line())
                msg = xpad + 'CPU affinity: ' + str(len(p['cpu_affinity'])) + ' cores'
                ret.append(self.curse_add_line(msg, splittable=True))
            # Second line is memory info
            if 'memory_info' in p and \
               p['memory_info'] is not None:
                ret.append(self.curse_new_line())
                msg = '{}Memory info: {}'.format(xpad, p['memory_info'])
                if 'memory_swap' in p and p['memory_swap'] is not None:
                    msg += ' swap ' + self.auto_unit(p['memory_swap'], low_precision=False)
                ret.append(self.curse_add_line(msg, splittable=True))
            # Third line is for open files/network sessions
            msg = ''
            if 'num_threads' in p and p['num_threads'] is not None:
                msg += str(p['num_threads']) + ' threads '
            if 'num_fds' in p and p['num_fds'] is not None:
                msg += str(p['num_fds']) + ' files '
            if 'num_handles' in p and p['num_handles'] is not None:
                msg += str(p['num_handles']) + ' handles '
            if 'tcp' in p and p['tcp'] is not None:
                msg += str(p['tcp']) + ' TCP '
            if 'udp' in p and p['udp'] is not None:
                msg += str(p['udp']) + ' UDP'
            if msg != '':
                ret.append(self.curse_new_line())
                msg = xpad + 'Open: ' + msg
                ret.append(self.curse_add_line(msg, splittable=True))
            # Fouth line is IO nice level (only Linux and Windows OS)
            if 'ionice' in p and \
               p['ionice'] is not None \
               and hasattr(p['ionice'], 'ioclass'):
                ret.append(self.curse_new_line())
                msg = xpad + 'IO nice: '
                k = 'Class is '
                v = p['ionice'].ioclass
                # Linux: The scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle.
                # Windows: On Windows only ioclass is used and it can be set to 2 (normal), 1 (low) or 0 (very low).
                if WINDOWS:
                    if v == 0:
                        msg += k + 'Very Low'
                    elif v == 1:
                        msg += k + 'Low'
                    elif v == 2:
                        msg += 'No specific I/O priority'
                    else:
                        msg += k + str(v)
                else:
                    if v == 0:
                        msg += 'No specific I/O priority'
                    elif v == 1:
                        msg += k + 'Real Time'
                    elif v == 2:
                        msg += k + 'Best Effort'
                    elif v == 3:
                        msg += k + 'IDLE'
                    else:
                        msg += k + str(v)
                #  value is a number which goes from 0 to 7.
                # The higher the value, the lower the I/O priority of the process.
                if hasattr(p['ionice'], 'value') and p['ionice'].value != 0:
                    msg += ' (value %s/7)' % str(p['ionice'].value)
                ret.append(self.curse_add_line(msg, splittable=True))

        return ret