def confirm(inputs): # "send?" message price = inputs.get("price", 0) if price > 0: cept_data = bytearray(Util.create_system_message(47, price)) else: cept_data = bytearray(Util.create_system_message(44)) cept_data.extend(Cept.set_cursor(24, 1)) cept_data.extend(Cept.sequence_end_of_page()) sys.stdout.buffer.write(cept_data) sys.stdout.flush() # TODO: use an editor for this, too! seen_a_one = False while True: c = Util.readchar() if c == "2": return False sys.stdout.write(c) sys.stdout.flush() break elif c == "1" and not seen_a_one: seen_a_one = True sys.stdout.write(c) sys.stdout.flush() elif c == "9" and seen_a_one: return True sys.stdout.write(c) sys.stdout.flush() break elif ord(c) == 8 and seen_a_one: seen_a_one = False sys.stdout.buffer.write(b'\b \b') sys.stdout.flush()
def set_color(self): cept_data = bytearray() if self.fgcolor is not None: cept_data.extend(Cept.set_fg_color(self.fgcolor)) if self.bgcolor is not None: cept_data.extend(Cept.set_bg_color(self.bgcolor)) return cept_data
def create_image_page(): # filename = "/Users/mist/Desktop/RGB_24bits_palette_sample_image.jpg" # filename = "/Users/mist/Desktop/Lenna_(test_image).png" # filename = "/Users/mist/Desktop/Wikipedia_logo_593.jpg" filename = "/Users/mist/Desktop/220px-C64c_system.jpg" (palette, drcs, chars) = Image_UI.cept_from_image(filename) data_cept = bytearray() data_cept.extend(Cept.define_palette(palette)) data_cept.extend(drcs) data_cept.extend(Cept.set_cursor(3, 1)) data_cept.extend(Cept.load_g0_drcs()) for l in chars: data_cept.extend(l) data_cept.extend(b'\r\n') meta = { "clear_screen": True, "links": { "0": "0" }, "publisher_color": 0 } return (meta, data_cept)
def line(): data_cept = bytearray() data_cept.extend(Cept.set_left_g3()) data_cept.extend(Cept.set_fg_color(15)) data_cept.extend(Cept.repeat("Q", 40)) data_cept.extend(Cept.set_fg_color(7)) data_cept.extend(Cept.set_left_g0()) return data_cept
def print_hint(self): if self.hint: cept_data = bytearray(Cept.service_break(24)) cept_data.extend(Cept.clear_line()) cept_data.extend(Cept.from_str(self.hint, 1)) cept_data.extend(Cept.hide_text()) cept_data.extend(Cept.service_break_back()) sys.stdout.buffer.write(cept_data) sys.stdout.flush()
def create_preamble(basedir, meta): global last_filename_include global last_filename_palette preamble = b'' # define palette if "palette" in meta: palette = meta["palette"] filename_palette = basedir + meta["palette"] + ".pal" sys.stderr.write("filename_palette = " + filename_palette + "\n") sys.stderr.write("last_filename_palette = " + last_filename_palette + "\n") if filename_palette != last_filename_palette: last_filename_palette = filename_palette with open(filename_palette) as f: sys.stderr.write("loading: '" + filename_palette + "'\n") palette = json.load(f) palette_data = Cept.define_palette(palette["palette"], palette.get("start_color", 16)) preamble += palette_data else: sys.stderr.write("skipping palette\n") else: last_filename_palette = "" if "include" in meta: if os.path.isfile( basedir + meta["include"] + ".inc"): filename_include_cm = basedir + meta["include"] + ".inc.cm" filename_include = basedir + meta["include"] + ".inc" else: filename_include_cm ="" filename_include = basedir + meta["include"] + ".cept" sys.stderr.write("Filename_include="+filename_include+"\n"); if ((filename_include != last_filename_include) or meta.get("clear_screen", False)): last_filename_include = filename_include if os.path.isfile(filename_include): with open(filename_include, mode='rb') as f: data_include = f.read() sys.stderr.write("loading: '" + filename_include + "'\n") elif os.path.isfile(filename_include_cm): data_include = CM.read(filename_include_cm) else: sys.stderr.write("include file not found.\n") # palette definition has to end with 0x1f; add one if # the include data doesn't start with one if data_include[0] != 0x1f: preamble += Cept.set_cursor(1, 1) preamble += data_include else: last_filename_include = "" b = baud if baud else 1200 if len(preamble) > (b/9) * SH291_THRESHOLD_SEC: preamble = Util.create_system_message(291) + preamble return preamble
def debug_print(s): sys.stderr.write("'") for cc in s: if cc == chr(Cept.ini()): sys.stderr.write("<INI>") if cc == chr(Cept.ter()): sys.stderr.write("<TER>") else: sys.stderr.write(cc) sys.stderr.write("'\n")
def wait_for_ter(): # TODO: use an editor for this, too! sys.stdout.buffer.write(Cept.sequence_end_of_page()) sys.stdout.flush() while True: c = Util.readchar() if ord(c) == Cept.ter(): sys.stdout.write(c) sys.stdout.flush() break cept_data = bytearray(Util.create_system_message(0)) cept_data.extend(Cept.sequence_end_of_page()) sys.stdout.buffer.write(cept_data) sys.stdout.flush()
def messaging_create_menu(title, items): data_cept = bytearray(Messaging_UI.messaging_create_title(title)) data_cept.extend(b"\n\r\n\r") i = 1 for item in items: data_cept.extend( Cept.from_str(str(i)) + b' ' + Cept.from_str(item)) data_cept.extend(b"\r\n\r\n") i += 1 data_cept.extend(b'\r\n\r\n\r\n\r\n\r\n\r\n') data_cept.extend(Cept.set_line_bg_color_simple(4)) data_cept.extend(b'0\x19\x2b') data_cept.extend(Cept.from_str(" Gesamtübersicht")) return data_cept
def create_system_message(code, price = 0): text = "" prefix = "SH" if code == 0: text = " " elif code == 10: text = "Rückblättern nicht möglich " elif code == 44: text = "Absenden? Ja:19 Nein:2 " elif code == 47: text = "Absenden für " + Util.format_currency(price) + "? Ja:19 Nein:2" elif code == 55: text = "Eingabe wird bearbeitet " elif code == 73: current_datetime = datetime.datetime.now().strftime("%d.%m.%Y %H:%M") text = "Abgesandt " + current_datetime + ", -> # " prefix = "1B" elif code == 100 or code == 101: text = "Seite nicht vorhanden " elif code == 291: text = "Seite wird aufgebaut " msg = bytearray(Cept.service_break(24)) msg.extend(Cept.clear_line()) msg.extend(Cept.from_str(text, 1)) msg.extend(Cept.hide_text()) msg.extend(b'\b') msg.extend(Cept.from_str(prefix)) msg.extend(Cept.from_str(str(code)).rjust(3, b'0')) msg.extend(Cept.service_break_back()) return msg
def insert_carriage_return(self): if self.__x != 0: self.__x = 0 if self.column == 1: sys.stdout.write("\r") else: sys.stdout.buffer.write( Cept.set_cursor(self.line + self.__y, self.column)) sys.stdout.buffer.write(self.set_color()) sys.stdout.flush()
def create_historic_main_page(): meta = { "publisher_name": "!BTX", "clear_screen": True, "links": { "0": "0", "10": "710", "11": "711", "#": "711" }, "publisher_color": 7 } data_cept = bytearray() data_cept.extend(Historic_UI.create_title("Historische Seiten")) data_cept.extend(b"\r\n") data_cept.extend( Cept.from_str("Nur wenige hundert der mehreren hundert-" "tausend BTX-Seiten sind überliefert.\n" "Die meisten entstammen dem Demomodus von" "Software-BTX-Decoderprogrammen.\n" "\n" "1988: C64 BTX Demo (Input 64 12/88)...--" "1989: Amiga BTX Terminal..............10" "1989: C64 BTX Demo (64'er 1/90).......--" "1991: BTX-VTX Manager v1.2............--" "1993: PC online 1&1...................11" "1994: MacBTX 1&1......................--" "1995: BTXTEST.........................--" "1996: RUN_ME..........................--" "\n" "Da historische Seiten erst angepaßt wer-" "den müssen, um nutzbar zu sein, sind\n" "noch nicht alle Sammlungen verfügbar." #XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX )) data_cept.extend(Historic_UI.footer("0 Zurück", None)) return (meta, Cept.compress(data_cept))
def btx_logo(): return Cept.from_aa( [ " ████████████████████████████████████████████████ ", " █ █ ", " █ █ ", " █ █", " █ █", " █ █", " █ ████████████████████ █", " █ ██████████████████████████ █", " █ ██████████████████████████████ █", " █ ████████████████████████████████ █", " █ ███████████ ███████████ █", " █ ██████████ ██████████ █", " █ ██████████ ████ ██████████ █", " █ █████████ ████████ █████████ █", " █ ██████ ██████████ ██████ █", " █ ███ ███ ██████████ ███ ███ █", " █ █████ ██████████ █████ █", " █ ███████ ██████████ ███████ █", " █ ████████ ██████████ ████████ █", " █ ████████ ██████████ ████████ █", " █ ████████ ██████████ ████████ █", " █ █████████ ████████ █████████ █", " █ ██████████ ████ ██████████ █", " █ ████████████ ████████████ █", " █ ████████████████████████████ █", " █ ████████████████████████████ █", " █ ████████████████████████████ █", " █ █", " █ █", " █ █", " █ ███ █ █ █ █ █ █", " █ █ █ █ █ █ █ █ █", " █ █ █ █ █ ███ ███ ██ ███ █ ██ █████ ██ ███ █ █ ██ █", " █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █", " █ █ █ █ █ █ █ ███ █ █ █ █ █ █ █ █ █ ███ █ █ █", " █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █", " █ ███ █ █ ███ ███ ██ █ █ █ █ █ █ █ ██ ███ █ █ ██ █", " █ █", " █ █", " █ █", " █ █ ", " █ █ ", " ████████████████████████████████████████████████ " ], 6 )
def footer(left, right): data_cept = bytearray() data_cept.extend(Cept.set_cursor(23, 1)) data_cept.extend(Cept.set_palette(0)) data_cept.extend(Cept.set_line_bg_color_simple(4)) data_cept.extend(Cept.from_str(left)) if right: data_cept.extend(Cept.set_cursor(23, 41 - len(right))) data_cept.extend(Cept.from_str(right)) return data_cept
def draw(self): cept_data = bytearray(Cept.parallel_limited_mode()) cept_data.extend(Cept.hide_cursor()) cept_data.extend(Cept.set_cursor(self.line, self.column)) fill_with_clear_line = self.clear_line and self.width == 40 # and self.height == 1 fill_with_spaces = self.clear_line and not fill_with_clear_line for i in range(0, self.height): l = self.__data[i].rstrip() if self.type == "password": l = "*" * len(l) else: if l.startswith(chr(Cept.ini())): l = "*" + l[1:] if l: cept_data.extend(self.set_color()) if fill_with_clear_line: cept_data.extend(Cept.clear_line()) if self.bgcolor: cept_data.extend(Cept.set_line_bg_color(self.bgcolor)) cept_data.extend(Cept.from_str(l)) if fill_with_spaces and len(l) > self.width: cept_data.extend(Cept.repeat(" ", self.width - len(l))) if i != self.height - 1: if self.column == 1: if self.width != 40 or fill_with_clear_line: cept_data.extend(b'\n') else: cept_data.extend( Cept.set_cursor(self.line + i + 1, self.column)) sys.stdout.buffer.write(cept_data) sys.stdout.flush()
def messaging_create_list(user, is_read): meta = { "publisher_name": "!BTX", "include": "a", "clear_screen": True, "publisher_color": 7 } if is_read: title = "Zurückgelegte Mitteilungen" else: title = "Neue Mitteilungen" data_cept = bytearray(Messaging_UI.messaging_create_title(title)) links = {"0": "8"} target_prefix = "89" if is_read else "88" messages = user.messaging.select(is_read, 0, 9) for index in range(0, 9): data_cept.extend(Cept.from_str(str(index + 1)) + b' ') if index < len(messages): message = messages[index] if message.from_user.org_name: data_cept.extend(Cept.from_str(message.from_user.org_name)) else: data_cept.extend( Cept.from_str(message.from_user.first_name)) data_cept.extend(b' ') data_cept.extend(Cept.from_str( message.from_user.last_name)) data_cept.extend(b'\r\n ') data_cept.extend(Cept.from_str(message.from_date())) data_cept.extend(b' ') data_cept.extend(Cept.from_str(message.from_time())) data_cept.extend(b'\r\n') links[str(index + 1)] = target_prefix + str(index + 1) else: data_cept.extend(b'\r\n\r\n') meta["links"] = links return (meta, data_cept)
def handle_inputs(inputs): # create editors and draw backgrounds editors = [] for input in inputs["fields"]: editor = Editor() editor.line = input["line"] editor.column = input["column"] editor.height = input["height"] editor.width = input["width"] editor.fgcolor = input.get("fgcolor") editor.bgcolor = input.get("bgcolor") editor.hint = input.get("hint") editor.type = input.get("type") editor.cursor_home = input.get("cursor_home", False) editor.legal_values = input.get("legal_values") editor.clear_line = input.get("clear_line", True) editor.end_on_illegal_character = input.get("end_on_illegal_character", False) editor.end_on_legal_string = input.get("end_on_legal_string", False) editor.echo_ter = input.get("echo_ter", False) editor.no_navigation = inputs.get("no_navigation", False) editor.string = input.get("default") editors.append(editor) editor.draw() # get all inputs input_data = {} i = 0 skip = False while i < len(inputs["fields"]): input = inputs["fields"][i] editor = editors[i] (val, dct) = editor.edit(skip) if dct: skip = True if val.startswith(chr(Cept.ini())): return { "$command": val[1:] } input_data[input["name"]] = val ret = decode_call(input.get("validate"), input_data) if not ret or ret == Util.VALIDATE_INPUT_OK: i += 1 if ret == Util.VALIDATE_INPUT_BAD: skip = False continue elif ret == Util.VALIDATE_INPUT_RESTART: i = 0 skip = False continue # confirmation if inputs.get("confirm", True): if confirm(inputs): if inputs.get("action") == "send_message": User.user().messaging.send(input_data["user_id"], input_data["ext"], input_data["body"]) system_message_sent_message() else: pass # TODO we stay on the page, in the navigator? elif not inputs.get("no_55", False): cept_data = Util.create_system_message(55) sys.stdout.buffer.write(cept_data) sys.stdout.flush() # send "input_data" to "inputs["target"]" if "target" in inputs: if inputs["target"].startswith("page:"): return { "$command": inputs["target"][5:] } ret = decode_call(inputs["target"], input_data) if ret: return { "$command": ret } else: return None # error else: return input_data
def create_page(pageid): ret = None # generated pages if pageid.startswith("00000") or pageid == "9a": # login ret = Login_UI.create_page(User.user(), pageid) basedir = PATH_DATA + "00000/" if not ret and (pageid.startswith("71") or pageid.startswith("78")): # historic page overview ret = Historic_UI.create_page(User.user(), pageid) basedir = PATH_DATA + "8/" if not ret and pageid.startswith("7"): # user management ret = User_UI.create_page(User.user(), pageid) basedir = PATH_DATA + "7/" if not ret and pageid.startswith("8"): # messaging ret = Messaging_UI.create_page(User.user(), pageid) basedir = PATH_DATA + "8/" if not ret and pageid.startswith("55"): # wikipedia basedir = PATH_DATA + "55/" ret = MediaWiki_UI.create_page(pageid, basedir) if not ret and pageid.startswith("35"): # Congress Wiki basedir = PATH_DATA + "55/" ret = MediaWiki_UI.create_page(pageid, basedir) if not ret and pageid.startswith("45"): # c64 wiki basedir = PATH_DATA + "45/" ret = MediaWiki_UI.create_page(pageid, basedir) if not ret and pageid.startswith("666"): # images ret = Image_UI.create_page(pageid) basedir = PATH_DATA + "55/" if not ret and pageid.startswith("6502"): # RSS basedir = PATH_DATA + "55/" ret = RSS_UI.create_page(pageid, basedir) if ret: (meta, data_cept) = ret else: basedir = None data_cept = None for dir in [ "", "hist/10/", "hist/11/" ]: for i in reversed(range(0, len(pageid))): testdir = PATH_DATA + dir + pageid[:i+1] if os.path.isdir(testdir): filename = pageid[i+1:] sys.stderr.write("filename: '" + filename + "'\n") basedir = testdir + "/" break if basedir: filename_meta = basedir + filename + ".meta" filename_cept = basedir + filename + ".cept" filename_cm = basedir + filename + ".cm" if os.path.isfile(filename_meta): with open(filename_meta) as f: meta = json.load(f) if os.path.isfile(filename_cept): with open(filename_cept, mode='rb') as f: data_cept = f.read() elif os.path.isfile(filename_cm): data_cept = CM.read(filename_cm) break if data_cept is None: return None try: with open(basedir + "a.glob") as f: glob = json.load(f) meta.update(glob) # combine dicts, glob overrides meta except: pass cept_1 = bytearray() cept_1.extend(Cept.hide_cursor()) if meta.get("clear_screen", False): cept_1.extend(Cept.serial_limited_mode()) cept_1.extend(Cept.clear_screen()) last_filename_include = "" sys.stderr.write("Clear Screen\n"); cept_1.extend(create_preamble(basedir, meta)) cept_2 = bytearray() if meta.get("cls2", False): cept_2.extend(Cept.serial_limited_mode()) cept_2.extend(Cept.clear_screen()) last_filename_include = "" # header if the data is actually there, if not ignore this try: hf = headerfooter(pageid, meta["publisher_name"], meta["publisher_color"]) cept_2.extend(hf) except: pass if meta.get("parallel_mode", False): cept_2.extend(Cept.parallel_mode()) # payload cept_2.extend(data_cept) cept_2.extend(Cept.serial_limited_mode()) # footer if it exists try: cept_2.extend(hf) except: pass cept_2.extend(Cept.sequence_end_of_page()) inputs = meta.get("inputs") return (cept_1, cept_2, meta["links"], inputs, meta.get("autoplay", False))
def create_historic_overview(collection, index): if collection == 10: name = "Amiga Demo" description = ("Der Amiga BTX Software-Decoder wurde mit" "Dumps von 113 BTX-Seiten aus 32\n" "Programmen ausgeliefert, sowie 56 eigens" "gestalteten Seiten zum Thema BTX.\n" "Die Seiten stammen vom April 1989.") distribution = [9, 17] start_page = ["20096/1", "Amiga Demo Startseite"] pages = [ ["1050", "Btx-Telex"], ["1188", "Teleauskunft"], ["1692", "Cityruf"], ["20000", "Deutsche Bundespost"], ["20096", "Commodore"], ["20511/223", "Kölner Stadtanzeiger"], ["21212", "Verbraucher-Zentrale NRW"], ["25800/0000", "Deutsche Bundesbahn"], ["30003", "Formel Eins"], ["30711", "Btx Südwest Datenbank GmbH"], ["33033", "Eden"], ["34034", "Frankfurter Allg. Zeitung"], ["34344", "Neue Mediengesellschaft Ulm"], ["35853", "ABIDA GmbH"], ["40040/200", "Axel Springer Verlag"], ["44479", "DIMDI"], ["50257", "Computerwelt Btx-Info-Dienst"], ["54004/04", "ÖVA Versicherungen"], ["57575", "Lotto Toto"], ["64064", "Markt & Technik"], ["65432/0", "ADAC"], ["67007", "Rheinpfalz Verlag/Druckerei"], ["201474/75", "Rhein-Neckar-Zeitung"], # [ "208585", "eba Pressebüro und Verlag [BROKEN]" ], ["208888", "Neue Mediengesellschaft Ulm"], ["402060", "AUTO & BTX WOLFSBURG"], ["50707545", "CHIP Magazin"], ["86553222", "Chaos Computer Club"], ["505050035", "Steinfels Sprachreisen"], ["920492040092", "Wolfgang Fritsch (BHP)"] ] elif collection == 11: name = "PC online 1&1" description = ("Der PC online 1&1 Decoder wurde mit\n" "von 25 BTX-Seiten aus 15 Programmen\n" "ausgeliefert. Die Seiten stammen vom\n" "November 1993.") distribution = [12] start_page = None pages = [["00000/88", "Teleauskunft"], ["00000/1188", "Mitteilungsdienst"], ["20111/1", "Vobis Microcomputer AG"], ["20111/11020", "- Übersicht 486"], ["20111/1102030", "- 486 DX-50 "], ["20111/110203010", "- 486 DX-50 Details"], ["21199", "Microsoft"], ["21199/1362", "- Produkte"], ["25800", "Deutsche Bundesbahn"], ["28000/101", "Postbank"], ["34561/10", "1&1 Telekommunkation"], ["34561/99", "- Forum [a-b]"], ["37107/2154", "WDR Computer-Club"], ["46801/8149999999", "Handelsblatt"], ["49498/0004902", "bhv Computerbücher"], ["49498/000490201", "- Neuheiten"], ["50000", "Deutsche Lufthansa"], ["52800", "IBM Deutschland"], ["52800/03", "- IBM Personal Systeme"], ["52800/31", "- HelpClubShop [a-c]"], ["58587/003", " ITZ Schulungen"], ["69010", "Deutscher Ind. Handelstag"], ["353535/00", "START Tourismus"], ["353535/01240", "- Veranstalter"], ["353535/01640", "- Reiseinformationen"]] else: return None start_with = 0 if index: for i in range(0, index): if i >= len(distribution): return None start_with += distribution[i] links = { "0": "78", } if start_page: links["10"] = Historic_UI.historic_link_from_str(start_page[0]) i = 20 for page in pages: links[str(i)] = Historic_UI.historic_link_from_str(page[0]) i += 1 meta = { "publisher_name": "!BTX", "clear_screen": True, "links": links, "publisher_color": 7 } sys.stderr.write("meta: " + pprint.pformat(meta) + "\n") data_cept = bytearray() data_cept.extend( Historic_UI.create_title("Historische Seiten: " + name)) data_cept.extend(b"\r\n") if not index: data_cept.extend(Cept.from_str(description)) data_cept.extend(b"\r\n\n") if start_page: data_cept.extend(Historic_UI.historic_line(start_page, 10)) data_cept.extend(b"\n") if index >= len(distribution): end = len(pages) else: end = start_with + distribution[index] for i in range(start_with, end): data_cept.extend(Historic_UI.historic_line(pages[i], i + 20)) right = "Weiter #" if index < len(distribution) else None data_cept.extend(Historic_UI.footer("0 Zurück", right)) return (meta, Cept.compress(data_cept))
sys.stderr.write("showing page: '" + desired_pageid + "'\n") try: ret = create_page(desired_pageid) except: error=10 success = ret is not None if success: (page_cept_data_1, page_cept_data_2, links, inputs, autoplay) = ret error = 0 if success else 100 else: error = 100 if error == 0: if (compress): page_cept_data_1 = Cept.compress(page_cept_data_1) page_cept_data_2 = Cept.compress(page_cept_data_2) sys.stderr.write("Sending pal/char: ") if send(page_cept_data_1): # send palette and charset sys.stderr.write("Sending text: ") send(page_cept_data_2) # if user didn't interrupt, send page text else: # user interrupted palette/charset, so the decoder state is undefined last_filename_palette = "" last_filename_include = "" # showing page worked current_pageid = desired_pageid if add_to_history: history.append(current_pageid) else:
def create_article_page(sheet_number): is_first_page = sheet_number == 0 if not RSS_UI.feed: RSS_UI.feed = feedparser.parse( "https://www.pagetable.com/?feed=rss2") entry = RSS_UI.feed["entries"][6] title = entry["title"] html = entry["content"][0]["value"] soup = BeautifulSoup(html, 'html.parser') page = Cept_page_from_HTML() page.soup = soup page.article_prefix = "XXX" page.insert_html_tags(soup.children) meta = { "clear_screen": True, "links": { "0": "0" }, "publisher_color": 0 } data_cept = bytearray() data_cept.extend(Cept.parallel_mode()) if is_first_page: data_cept.extend(Cept.set_screen_bg_color(7)) data_cept.extend(Cept.set_cursor(2, 1)) data_cept.extend(Cept.set_line_bg_color(0)) data_cept.extend(b'\n') data_cept.extend(Cept.set_line_bg_color(0)) data_cept.extend(Cept.double_height()) data_cept.extend(Cept.set_fg_color(7)) data_cept.extend(Cept.from_str(title[:39])) data_cept.extend(b'\r\n') data_cept.extend(Cept.normal_size()) data_cept.extend(b'\n') # print navigation # * on sheet 0, so we don't have to print it again on later sheets # * on the last sheet, because it doesn't show the "#" text # * on the second last sheet, because navigating back from the last one needs to show "#" again if sheet_number == 0 or sheet_number >= page.number_of_sheets() - 2: data_cept.extend(Cept.set_cursor(23, 1)) data_cept.extend(Cept.set_line_bg_color(0)) data_cept.extend(Cept.set_fg_color(7)) data_cept.extend(Cept.from_str("0 < Back")) s = "# > Next" data_cept.extend(Cept.set_cursor(23, 41 - len(s))) if sheet_number == page.number_of_sheets() - 1: data_cept.extend(Cept.repeat(" ", len(s))) else: data_cept.extend(Cept.from_str(s)) data_cept.extend(Cept.set_cursor(5, 1)) # add text data_cept.extend(page.cept_for_sheet(sheet_number)) return (meta, data_cept)
def messaging_create_message_detail(user, index, is_read): messages = user.messaging.select(is_read, index, 1) if len(messages) == 0: return None message = messages[0] meta = { "publisher_name": "Bildschirmtext", "include": "11a", "palette": "11a", "clear_screen": True, "links": { "0": "89" if is_read else "88", }, "publisher_color": 7 } from_date = message.from_date() from_time = message.from_time() if message.from_user.personal_data: from_street = message.from_user.street from_zip = message.from_user.zip from_city = message.from_user.city else: from_street = "" from_zip = "" from_city = "" data_cept = bytearray(Cept.parallel_limited_mode()) data_cept.extend(Cept.set_cursor(2, 1)) data_cept.extend(Cept.set_fg_color(3)) data_cept.extend(b'von ') data_cept.extend( Cept.from_str(message.from_user.user_id.ljust(12)) + b' ' + Cept.from_str(message.from_user.ext.rjust(5, '0'))) data_cept.extend(Cept.set_cursor(2, 41 - len(from_date))) data_cept.extend(Cept.from_str(from_date)) data_cept.extend(Cept.repeat(" ", 4)) data_cept.extend(Cept.from_str(message.from_user.org_name)) data_cept.extend(Cept.set_cursor(3, 41 - len(from_time))) data_cept.extend(Cept.from_str(from_time)) data_cept.extend(Cept.repeat(" ", 4)) data_cept.extend(Cept.set_fg_color_simple(0)) data_cept.extend( Cept.from_str(message.from_user.first_name) + b' ' + Cept.from_str(message.from_user.last_name)) data_cept.extend(b'\r\n') data_cept.extend(Cept.repeat(" ", 4)) data_cept.extend(Cept.from_str(from_street)) data_cept.extend(b'\r\n') data_cept.extend(Cept.repeat(" ", 4)) data_cept.extend(Cept.from_str(from_zip)) data_cept.extend(b' ') data_cept.extend(Cept.from_str(from_city)) data_cept.extend(b'\r\n') data_cept.extend(b'an ') data_cept.extend( Cept.from_str(user.user_id.ljust(12)) + b' ' + Cept.from_str(user.ext.rjust(5, '0'))) data_cept.extend(b'\r\n') data_cept.extend(Cept.repeat(" ", 4)) data_cept.extend( Cept.from_str(user.first_name) + b' ' + Cept.from_str(user.last_name)) data_cept.extend(b'\r\n\n') data_cept.extend(Cept.from_str(message.body())) data_cept.extend(Cept.set_cursor(23, 1)) data_cept.extend(b'0') data_cept.extend(b'\x1b\x29\x20\x40' # load DRCs into G1 b'\x1b\x7e' # G1 into right charset ) data_cept.extend(Cept.from_str(" Gesamtübersicht")) data_cept.extend(Cept.repeat(" ", 22)) user.messaging.mark_as_read(message.index) return (meta, data_cept)
def messaging_create_compose(user): meta = { "include": "a", "clear_screen": True, "links": { "0": "8" }, "publisher_color": 7, "inputs": { "fields": [{ "name": "user_id", "type": "user_id", "line": 8, "column": 20, "height": 1, "width": 16, "bgcolor": 4, "fgcolor": 3, "validate": "call:Messaging_UI.callback_validate_user_id" }, { "name": "ext", "type": "ext", "line": 8, "column": 37, "height": 1, "width": 1, "bgcolor": 4, "fgcolor": 3, "default": "1", "validate": "call:Messaging_UI.callback_validate_ext" }, { "name": "body", "line": 12, "column": 1, "height": 10, "width": 40, "bgcolor": 4, "fgcolor": 3 }], "action": "send_message", "price": 30, "target": "page:8" } } current_date = datetime.datetime.now().strftime("%d.%m.%Y") current_time = datetime.datetime.now().strftime("%H:%M") data_cept = bytearray(Cept.set_cursor(2, 1)) data_cept.extend(Cept.set_palette(1)) data_cept.extend(Cept.set_screen_bg_color_simple(4)) data_cept.extend(b'\x1b\x28\x40' # load G0 into G0 ) data_cept.extend(b'\x0f' # G0 into left charset ) data_cept.extend(Cept.parallel_mode()) data_cept.extend(Cept.set_palette(0)) data_cept.extend(Cept.code_9e()) data_cept.extend(b'\n\r') data_cept.extend(Cept.set_line_bg_color_simple(4)) data_cept.extend(b'\n') data_cept.extend(Cept.set_line_bg_color_simple(4)) data_cept.extend(Cept.set_palette(1)) data_cept.extend(Cept.double_height()) data_cept.extend(b'\r') data_cept.extend(Cept.from_str("Mitteilungsdienst")) data_cept.extend(b'\n\r') data_cept.extend(Cept.set_palette(0)) data_cept.extend(Cept.normal_size()) data_cept.extend(Cept.code_9e()) data_cept.extend(Cept.set_fg_color_simple(7)) data_cept.extend(Cept.from_str("Absender:")) data_cept.extend(Cept.from_str(user.user_id)) data_cept.extend(Cept.set_cursor(5, 25)) data_cept.extend(Cept.from_str(user.ext)) data_cept.extend(Cept.set_cursor(6, 10)) data_cept.extend(Cept.from_str(user.first_name)) data_cept.extend(Cept.set_cursor(7, 10)) data_cept.extend(Cept.from_str(user.last_name)) data_cept.extend(Cept.set_cursor(5, 31)) data_cept.extend(Cept.from_str(current_date)) data_cept.extend(Cept.set_cursor(6, 31)) data_cept.extend(Cept.from_str(current_time)) data_cept.extend(b'\r\n\n') data_cept.extend(Cept.from_str("Tln.-Nr. Empfänger:")) data_cept.extend(Cept.set_cursor(8, 36)) data_cept.extend(b'-' b'\r\n\n\n') data_cept.extend(b'Text:') data_cept.extend(b'\r\n\n\n\n\n\n\n\n\n\n\n\n') data_cept.extend(Cept.set_line_bg_color_simple(4)) data_cept.extend(b'0') data_cept.extend(b'\x19' # switch to G2 for one character b'\x2b\xfe\x7f' # "+." ) return (meta, data_cept)
try: ret = create_page(desired_pageid) except: error = 10 success = ret is not None if success: (page_cept_data_1, page_cept_data_2, links, inputs, autoplay) = ret error = 0 if success else 100 else: error = 100 if error == 0: if (compress): page_cept_data_1 = Cept.compress(page_cept_data_1) page_cept_data_2 = Cept.compress(page_cept_data_2) sys.stderr.write("Sending pal/char: ") if send(page_cept_data_1): # send palette and charset sys.stderr.write("Sending text: ") send(page_cept_data_2) # if user didn't interrupt, send page text else: # user interrupted palette/charset, so the decoder state is undefined last_filename_palette = "" last_filename_include = "" # showing page worked current_pageid = desired_pageid if add_to_history: history.append(current_pageid) else:
def headerfooter(pageid, publisher_name, publisher_color): hide_header_footer = len(publisher_name) == 0 hide_price = False # Early screenshots had a two-line publisher name with # the BTX logo in it for BTX-internal pages. Some .meta # files still reference this, but we should remove this. if publisher_name == "!BTX": # publisher_name = ( # b'\x1b\x22\x41' # parallel mode # b'\x9b\x30\x40' # select palette #0 # b'\x9e' # ??? # b'\x87' # set fg color to #7 # b'\x1b\x28\x20\x40' # load DRCs into G0 # b'\x0f' # G0 into left charset # b'\x21\x22\x23' # "!"#" # b'\n' # b'\r' # b'\x24\x25\x26' # "$%&" # b'\x0b' # cursor up # b'\x09' # cursor right # b'\x1b\x28\x40' # load G0 into G0 # b'\x0f' # G0 into left charset # b'\n' # b'\x8d' # double height # # TODO: this does not draw!! :( # b'Bildschirmtext' # ) publisher_name = "Bildschirmtext" hide_price = True else: publisher_name = publisher_name[:30] hf = bytearray(Cept.set_res_40_24()) hf.extend(Cept.set_cursor(23, 1)) hf.extend(Cept.unprotect_line()) hf.extend(Cept.set_line_fg_color_simple(12)) hf.extend(Cept.parallel_limited_mode()) hf.extend(Cept.set_cursor(24, 1)) hf.extend(Cept.unprotect_line()) hf.extend(b' \b') hf.extend(Cept.clear_line()) hf.extend(Cept.cursor_home()) hf.extend(Cept.unprotect_line()) hf.extend(b' \b') hf.extend(Cept.clear_line()) hf.extend(Cept.serial_limited_mode()) hf.extend(Cept.set_cursor(24, 1)) hf.extend(Cept.set_fg_color(8)) hf.extend(b'\b') hf.extend(Cept.code_9d()) hf.extend(b'\b') if publisher_color < 8: color_string = Cept.set_fg_color(publisher_color) else: color_string = Cept.set_fg_color_simple(publisher_color - 8) hf.extend(color_string) hf.extend(Cept.set_cursor(24, 19)) if not hide_header_footer: hf.extend(Cept.from_str(pageid).rjust(22)) hf.extend(Cept.cursor_home()) hf.extend(Cept.set_palette(1)) hf.extend(Cept.set_fg_color(8)) hf.extend(b'\b') hf.extend(Cept.code_9d()) hf.extend(b'\b') hf.extend(color_string) hf.extend(b'\r') hf.extend(Cept.from_str(publisher_name)) # TODO: price if not hide_header_footer and not hide_price: hf.extend(Cept.set_cursor(1, 31)) hf.extend(b' ') hf.extend(Cept.from_str(Util.format_currency(0))) hf.extend(Cept.cursor_home()) hf.extend(Cept.set_palette(0)) hf.extend(Cept.protect_line()) hf.extend(b'\n') return hf
def messaging_create_title(title): data_cept = bytearray(Cept.set_cursor(2, 1)) data_cept.extend(Cept.set_palette(1)) data_cept.extend(Cept.set_screen_bg_color_simple(4)) data_cept.extend(b'\x1b\x28\x40' # load G0 into G0 b'\x0f' # G0 into left charset ) data_cept.extend(Cept.parallel_mode()) data_cept.extend(Cept.set_palette(0)) data_cept.extend(Cept.code_9e()) data_cept.extend(b'\n\r') data_cept.extend(Cept.set_line_bg_color_simple(4)) data_cept.extend(b'\n') data_cept.extend(Cept.set_line_bg_color_simple(4)) data_cept.extend(Cept.set_palette(1)) data_cept.extend(Cept.double_height()) data_cept.extend(b'\r') data_cept.extend(Cept.from_str(title)) data_cept.extend(b'\n\r') data_cept.extend(Cept.set_palette(0)) data_cept.extend(Cept.normal_size()) data_cept.extend(Cept.code_9e()) data_cept.extend(Cept.set_fg_color_simple(7)) return data_cept
def create_add_user(): meta = { "publisher_name": "!BTX", "include": "a", "clear_screen": True, "links": { "0": "0", "1": "88", "2": "89", "5": "810" }, "inputs": { "fields": [ { "name": "user_id", "hint": "Gewünschte Nummer oder # eingeben", "line": 6, "column": 19, "height": 1, "width": 10, "bgcolor": 12, "fgcolor": 3, "type": "number", "validate": "call:User_UI.callback_validate_user_id" }, { "name": "salutation", "hint": "Anrede oder # eingeben", "line": 7, "column": 9, "height": 1, "width": 20, "bgcolor": 12, "fgcolor": 3 }, { "name": "last_name", "hint": "Nachnamen oder # eingeben", "line": 8, "column": 7, "height": 1, "width": 20, "bgcolor": 12, "validate": "call:User_UI.callback_validate_last_name", "fgcolor": 3 }, { "name": "first_name", "hint": "Vornamen oder # eingeben", "line": 9, "column": 10, "height": 1, "width": 20, "bgcolor": 12, "fgcolor": 3 }, { "name": "street", "hint": "Straße und Hausnummer oder # eingeben", "line": 10, "column": 9, "height": 1, "width": 20, "bgcolor": 12, "fgcolor": 3 }, { "name": "zip", "hint": "Postleitzahl oder # eingeben", "line": 11, "column": 6, "height": 1, "width": 5, "bgcolor": 12, "fgcolor": 3, "type": "number" }, { "name": "city", "hint": "Ort oder # eingeben", "line": 11, "column": 17, "height": 1, "width": 13, "bgcolor": 12, "fgcolor": 3 }, { "name": "country", "hint": "Land oder # eingeben", "line": 11, "column": 37, "height": 1, "width": 2, "bgcolor": 12, "fgcolor": 3, "default": "de", "type": "alpha", "cursor_home": True, "overwrite": True }, { "name": "block_payments", "hint": "j/n oder # eingeben", "line": 13, "column": 25, "height": 1, "width": 1, "bgcolor": 12, "fgcolor": 3, "default": "n", "cursor_home": True, "legal_values": ["j", "n"] }, { "name": "block_fees", "hint": "j/n oder # eingeben", "line": 14, "column": 25, "height": 1, "width": 1, "bgcolor": 12, "fgcolor": 3, "default": "n", "cursor_home": True, "legal_values": ["j", "n"] }, { "name": "pocket_money_major", "hint": "0-9 oder # eingeben", "line": 15, "column": 34, "height": 1, "width": 1, "bgcolor": 12, "fgcolor": 3, "default": "9", "type": "number", "cursor_home": True, "overwrite": True }, { "name": "pocket_money_minor", "hint": "00-99 oder # eingeben", "line": 15, "column": 36, "height": 1, "width": 2, "bgcolor": 12, "fgcolor": 3, "default": "99", "type": "number", "cursor_home": True, "overwrite": True }, { "name": "max_price_major", "hint": "0-9 oder # eingeben", "line": 16, "column": 34, "height": 1, "width": 1, "bgcolor": 12, "fgcolor": 3, "default": "9", "type": "number", "cursor_home": True, "overwrite": True }, { "name": "max_price_minor", "hint": "00-99 oder # eingeben", "line": 16, "column": 36, "height": 1, "width": 2, "bgcolor": 12, "fgcolor": 3, "default": "99", "type": "number", "cursor_home": True, "overwrite": True }, { "name": "password", "hint": "Neues Kennwort", "line": 19, "column": 11, "height": 1, "width": 14, "bgcolor": 12, "fgcolor": 3, "type": "password", "validate": "call:User_UI.callback_validate_password", }, ], "confirm": False, "target": "call:User_UI.callback_add_user", }, "publisher_color": 7 } data_cept = bytearray() data_cept.extend(User_UI.create_title("Neuen Benutzer einrichten")) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("Teilnehmernummer:")) data_cept.extend(Cept.set_cursor(6, 29)) data_cept.extend(Cept.from_str("-1")) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("Anrede:")) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("Name:")) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("Vorname:")) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("Straße:")) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("PLZ:")) data_cept.extend(Cept.repeat(" ", 7)) data_cept.extend(Cept.from_str("Ort:")) data_cept.extend(Cept.set_cursor(11, 31)) data_cept.extend(Cept.from_str("Land:")) data_cept.extend(b"\r\n") data_cept.extend(User_UI.line()) data_cept.extend(Cept.from_str("Vergütungssperre aktiv:")) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("Gebührensperre aktiv:")) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("Taschengeldkonto :")) data_cept.extend(Cept.set_cursor(15, 35)) data_cept.extend(Cept.from_str(", DM")) data_cept.extend(Cept.from_str("Max. Vergütung/Seite :")) data_cept.extend(Cept.set_cursor(16, 35)) data_cept.extend(Cept.from_str(", DM")) data_cept.extend(User_UI.line()) data_cept.extend(b"\r\n") data_cept.extend(Cept.from_str("Kennwort: ")) data_cept.extend(b"\r\n\r\n") data_cept.extend(User_UI.line()) return (meta, data_cept)
def create_custom_system_message(text): msg = bytearray(Cept.service_break(24)) msg.extend(Cept.clear_line()) msg.extend(Cept.from_str(text, 1)) msg.extend(Cept.service_break_back()) return msg
def create_search_page(mediawiki, basedir): meta = { "clear_screen": True, "links": { "0": "0" }, "inputs": { "fields": [{ "name": "search", "line": 18, "column": 9, "height": 1, "width": 31, "bgcolor": 0, "fgcolor": 15, "validate": "call:MediaWiki_UI.callback_validate_search:" + str(mediawiki.id) }], "confirm": False, "target": "call:MediaWiki_UI.callback_search:" + str(mediawiki.id) }, "publisher_color": 0 } data_cept = bytearray() data_cept.extend(Cept.parallel_mode()) data_cept.extend(Cept.set_screen_bg_color(7)) data_cept.extend(Cept.set_cursor(2, 1)) data_cept.extend(Cept.set_line_bg_color(0)) data_cept.extend(b'\n') data_cept.extend(Cept.set_line_bg_color(0)) data_cept.extend(Cept.double_height()) data_cept.extend(Cept.set_fg_color(7)) data_cept.extend(Cept.from_str(mediawiki.title)) data_cept.extend(b'\r\n') data_cept.extend(Cept.normal_size()) data_cept.extend(b'\n') data_cept.extend(Cept.set_cursor(18, 1)) data_cept.extend(Cept.set_fg_color(0)) data_cept.extend(Cept.from_str(mediawiki.search_string)) # trick: show cursor now so that user knows they can enter text, even though more # data is loading data_cept.extend(Cept.show_cursor()) image = Image_UI(basedir + "wikipedia.png", colors=4) data_cept.extend(Cept.define_palette(image.palette)) data_cept.extend(image.drcs) data_cept.extend(Cept.hide_cursor()) y = 6 for l in image.chars: data_cept.extend( Cept.set_cursor(y, int((41 - len(image.chars[0])) / 2))) data_cept.extend(Cept.load_g0_drcs()) data_cept.extend(l) y += 1 return (meta, data_cept)
def edit(self, skip_entry=False): start = True dct = False prefix = bytearray() inject_char = None while True: if start and not skip_entry: start = False self.print_hint() cept_data = bytearray() self.__y = 0 if self.height > 1 or self.cursor_home: cept_data.extend(Cept.set_cursor(self.line, self.column)) self.__x = 0 else: cept_data.extend( Cept.set_cursor(self.line, self.column + len(self.string))) self.__x = len(self.string) if self.fgcolor: cept_data.extend(Cept.set_fg_color(self.fgcolor)) if self.bgcolor: cept_data.extend(Cept.set_bg_color(self.bgcolor)) cept_data.extend(Cept.show_cursor()) sys.stdout.buffer.write(cept_data) sys.stdout.flush() if skip_entry: sys.stderr.write("skipping\n") break if inject_char: c = inject_char inject_char = None else: c = Util.readchar() sys.stderr.write("In: " + hex(ord(c)) + "\n") if self.command_mode and ord( c) == Cept.ini() and self.string[-1:] == chr(Cept.ini()): # exit command mode, tell parent to clear return (None, False) c2 = Cept.code_to_str(prefix + bytes([ord(c)])) if c2 is None: # sequence not complete prefix.append(ord(c)) continue prefix = bytearray() if c2 == "": # we couldn't decode it continue c = c2 # if c < 0x20 # c is a CEPT control code # if c >= 0x20 # c is Unicode if ord(c) < 0x20: #and ord(c) != Cept.ini(): prefix = bytearray() if ord(c) == Cept.ini(): if not self.command_mode: is_editor_code = False sys.stderr.write("entering command mode\n") editor = Editor() editor.line = 24 editor.column = 1 editor.height = 1 editor.width = 20 editor.string = chr(Cept.ini()) editor.command_mode = True editor.clear_line = True editor.echo_ter = True editor.draw() (val, dct) = editor.edit() sys.stderr.write("exited command mode\n") if val is None: # "**" in command mode self.string = "" self.draw() else: Editor.debug_print(val) if val.startswith(chr(Cept.ini()) + "02") and len(val) == 4: # editor codes *021# etc. is_editor_code = True code = int(val[3:]) map = { 1: "\r", # CR 2: "\x0b", # UP 4: "\x08", # LEFT 6: "\x09", # RIGHT 8: "\n", # DOWN 9: "\x1a" # DCT } c = map.get(code) if c is not None: inject_char = c else: sys.stderr.write( "ignoring invalid editor code\n") else: # global code if not self.no_navigation or val == chr( Cept.ini()) + "00" or val == chr( Cept.ini()) + "09": return (val, False) sys.stderr.write("ignoring navigation\n") start = True continue elif ord(c) == Cept.ter(): if self.echo_ter: sys.stdout.write("#") sys.stdout.flush() break elif ord(c) == Cept.dct(): dct = True break self.insert_control_character(c) else: # ord(c) >= 0x20 character_legal = True string_legal = False # CEPT doesn't have a concept of backspace, so the backspace key # sends the sequence CSR_LEFT, SPACE, CSR_LEFT. It is very tricky # to detect this properly, so we will just allow spaces in # "number" and "alpha" input fields. if self.type == "number" and not c.isdigit() and not c == " ": character_legal = False elif self.type == "alpha" and not c.isalpha() and not c == " ": character_legal = False elif self.legal_values: s = self.try_insert_character(c).rstrip() character_legal = False for legal_input in self.legal_values: if s == legal_input: character_legal = True string_legal = True # sys.stderr.write("string_legal!\n") break elif legal_input.startswith(s): character_legal = True # sys.stderr.write("character_legal!\n") break if character_legal or self.end_on_illegal_character: if self.insert_character(c): if self.type == "password": sys.stdout.write("*") else: sys.stdout.buffer.write(Cept.from_str(c)) sys.stdout.flush() if not character_legal and self.end_on_illegal_character: break if string_legal and self.end_on_legal_string: break # sys.stderr.write("self.__data:\n" + pprint.pformat(self.__data) + "\n") # sys.stderr.write("self.string:\n" + pprint.pformat(self.string) + "\n") return (self.string, dct)